| Files: | 191 |
|---|---|
| Lines: | 45000 |
| Covered: | 1124 / 8507 (13.2%) |
| Lines covered: | 0 / 38 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.15; |
||
| 3 | |||
| 4 |
import "forge-std/console2.sol"; |
||
| 5 |
import {Script} from "forge-std/Script.sol";
|
||
| 6 |
import {UintString} from "./utils/UintString.sol";
|
||
| 7 | |||
| 8 |
contract GasSnapshot is Script {
|
||
| 9 |
error GasMismatch(uint256 oldGas, uint256 newGas); |
||
| 10 | |||
| 11 |
/// @notice if this environment variable is true, we revert on gas mismatch |
||
| 12 |
string public constant CHECK_ENV_VAR = "FORGE_SNAPSHOT_CHECK"; |
||
| 13 |
/// @notice save gas snapshots in this dir |
||
| 14 |
string public constant SNAP_DIR = ".forge-snapshots/"; |
||
| 15 |
/// @notice gas overhead for the snapshotting function itself |
||
| 16 |
uint256 private constant GAS_CALIBRATION = 100; |
||
| 17 | |||
| 18 |
/// @notice if true, revert on gas mismatch, else overwrite with new values |
||
| 19 |
bool internal check; |
||
| 20 |
/// @notice Transient variable for the start gas |
||
| 21 |
uint256 private cachedGas; |
||
| 22 |
/// @notice Transient variable for the snapshot name |
||
| 23 |
string private cachedName; |
||
| 24 | |||
| 25 |
constructor() {
|
||
| 26 |
_mkdirp(SNAP_DIR); |
||
| 27 |
//try vm.envBool(CHECK_ENV_VAR) returns (bool _check) {
|
||
| 28 |
// check = _check; |
||
| 29 |
//} catch {
|
||
| 30 |
// check = false; |
||
| 31 |
//} |
||
| 32 |
} |
||
| 33 | |||
| 34 |
/// @notice Write a size snapshot with the given name |
||
| 35 |
/// @param target the contract to snapshot the size of |
||
| 36 |
/// @dev The next call to `snapEnd` will end the snapshot |
||
| 37 |
function snapSize(string memory name, address target) internal {
|
||
| 38 |
uint256 size = target.code.length; |
||
| 39 |
if (check) {
|
||
| 40 |
_checkSnapshot(name, size); |
||
| 41 |
} else {
|
||
| 42 |
_writeSnapshot(name, size); |
||
| 43 |
} |
||
| 44 |
} |
||
| 45 | |||
| 46 |
/// @notice Snapshot the given value |
||
| 47 |
function snap(string memory name, uint256 value) internal {
|
||
| 48 |
if (check) {
|
||
| 49 |
_checkSnapshot(name, value); |
||
| 50 |
} else {
|
||
| 51 |
_writeSnapshot(name, value); |
||
| 52 |
} |
||
| 53 |
} |
||
| 54 | |||
| 55 |
/// @notice Snapshot the given external closure |
||
| 56 |
function snap(string memory name, function() external fn) internal {
|
||
| 57 |
uint256 gasBefore = gasleft(); |
||
| 58 |
fn(); |
||
| 59 |
uint256 gasUsed = gasBefore - gasleft(); |
||
| 60 |
if (check) {
|
||
| 61 |
_checkSnapshot(name, gasUsed); |
||
| 62 |
} else {
|
||
| 63 |
_writeSnapshot(name, gasUsed); |
||
| 64 |
} |
||
| 65 |
} |
||
| 66 | |||
| 67 |
/// @notice Snapshot the given internal closure |
||
| 68 |
function snap(string memory name, function() internal fn) internal {
|
||
| 69 |
uint256 gasBefore = gasleft(); |
||
| 70 |
fn(); |
||
| 71 |
uint256 gasUsed = gasBefore - gasleft(); |
||
| 72 |
if (check) {
|
||
| 73 |
_checkSnapshot(name, gasUsed); |
||
| 74 |
} else {
|
||
| 75 |
_writeSnapshot(name, gasUsed); |
||
| 76 |
} |
||
| 77 |
} |
||
| 78 | |||
| 79 |
/// @notice Snapshot using forge isolate of gas of the previous call |
||
| 80 |
/// @dev most accurate as this uses a complete transaction and no storage semantics |
||
| 81 |
function snapLastCall(string memory name) internal {
|
||
| 82 |
uint256 gasUsed = vm.lastCallGas().gasTotalUsed; |
||
| 83 |
if (check) {
|
||
| 84 |
_checkSnapshot(name, gasUsed); |
||
| 85 |
} else {
|
||
| 86 |
_writeSnapshot(name, gasUsed); |
||
| 87 |
} |
||
| 88 |
} |
||
| 89 | |||
| 90 |
/// @notice Start a snapshot with the given name |
||
| 91 |
/// @dev The next call to `snapEnd` will end the snapshot |
||
| 92 |
function snapStart(string memory name) internal {
|
||
| 93 |
// warm up cachedGas so the only sstore after calling `gasleft` is exactly 100 gas |
||
| 94 |
cachedGas = 1; |
||
| 95 |
cachedName = name; |
||
| 96 |
cachedGas = gasleft(); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
/// @notice End the current snapshot |
||
| 100 |
/// @dev Must be called after a call to `snapStart`, else reverts with underflow |
||
| 101 |
function snapEnd() internal {
|
||
| 102 |
uint256 newGasLeft = gasleft(); |
||
| 103 |
// subtract original gas and snapshot gas overhead |
||
| 104 |
uint256 gasUsed = cachedGas - newGasLeft - GAS_CALIBRATION; |
||
| 105 |
// reset to 0 so all writes for consistent overhead handling |
||
| 106 |
cachedGas = 0; |
||
| 107 | |||
| 108 |
if (check) {
|
||
| 109 |
_checkSnapshot(cachedName, gasUsed); |
||
| 110 |
} else {
|
||
| 111 |
_writeSnapshot(cachedName, gasUsed); |
||
| 112 |
} |
||
| 113 |
} |
||
| 114 | |||
| 115 |
/// @notice Check the gas usage against the snapshot. Revert on mismatch |
||
| 116 |
function _checkSnapshot(string memory name, uint256 gasUsed) internal view {
|
||
| 117 |
uint256 oldGasUsed = _readSnapshot(name); |
||
| 118 |
if (oldGasUsed != gasUsed) {
|
||
| 119 |
revert GasMismatch(oldGasUsed, gasUsed); |
||
| 120 |
} |
||
| 121 |
} |
||
| 122 | |||
| 123 |
/// @notice Read the last snapshot value from the file |
||
| 124 |
function _readSnapshot(string memory name) private view returns (uint256 res) {
|
||
| 125 |
string memory oldValue = vm.readLine(_getSnapFile(name)); |
||
| 126 |
res = UintString.stringToUint(oldValue); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
/// @notice Write the new snapshot value to file |
||
| 130 |
function _writeSnapshot(string memory name, uint256 gasUsed) private {
|
||
| 131 |
vm.writeFile(_getSnapFile(name), vm.toString(gasUsed)); |
||
| 132 |
} |
||
| 133 | |||
| 134 |
/// @notice Make the directory for snapshots |
||
| 135 |
function _mkdirp(string memory dir) private {
|
||
| 136 |
string[] memory mkdirp = new string[](3); |
||
| 137 |
mkdirp[0] = "mkdir"; |
||
| 138 |
mkdirp[1] = "-p"; |
||
| 139 |
mkdirp[2] = dir; |
||
| 140 |
vm.ffi(mkdirp); |
||
| 141 |
} |
||
| 142 | |||
| 143 |
/// @notice Get the snapshot file name |
||
| 144 |
function _getSnapFile(string memory name) private pure returns (string memory) {
|
||
| 145 |
return string(abi.encodePacked(SNAP_DIR, name, ".snap")); |
||
| 146 |
} |
||
| 147 | |||
| 148 |
/// @notice sets the library to check mode |
||
| 149 |
function setCheckMode(bool _check) internal {
|
||
| 150 |
check = _check; |
||
| 151 |
} |
||
| 152 |
} |
||
| 153 |
| Lines covered: | 0 / 11 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.15; |
||
| 3 | |||
| 4 |
library UintString {
|
||
| 5 |
error InvalidStringNumber(string s); |
||
| 6 | |||
| 7 |
/// @notice converts the given string s into a uint256 |
||
| 8 |
function stringToUint(string memory s) internal pure returns (uint256 result) {
|
||
| 9 |
bytes memory b = bytes(s); |
||
| 10 |
uint256 oldResult; |
||
| 11 |
for (uint256 i; i < b.length;) {
|
||
| 12 |
// c = b[i] was not needed |
||
| 13 |
if (uint8(b[i]) >= 48 && uint8(b[i]) <= 57) {
|
||
| 14 |
// store old value so we can check for overflows |
||
| 15 |
oldResult = result; |
||
| 16 |
result = result * 10 + (uint8(b[i]) - 48); |
||
| 17 |
if (oldResult > result) {
|
||
| 18 |
// we can only get here if the result overflowed and is smaller than last stored value |
||
| 19 |
revert InvalidStringNumber(s); |
||
| 20 |
} |
||
| 21 |
} else {
|
||
| 22 |
revert InvalidStringNumber(s); |
||
| 23 |
} |
||
| 24 |
unchecked {
|
||
| 25 |
++i; |
||
| 26 |
} |
||
| 27 |
} |
||
| 28 |
} |
||
| 29 |
} |
||
| 30 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
import {StdStorage} from "./StdStorage.sol";
|
||
| 5 |
import {Vm, VmSafe} from "./Vm.sol";
|
||
| 6 | |||
| 7 |
abstract contract CommonBase {
|
||
| 8 |
// Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. |
||
| 9 |
address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
|
||
| 10 |
// console.sol and console2.sol work by executing a staticcall to this address. |
||
| 11 |
address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; |
||
| 12 |
// Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. |
||
| 13 |
address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; |
||
| 14 |
// Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. |
||
| 15 |
address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller"))));
|
||
| 16 |
// Address of the test contract, deployed by the DEFAULT_SENDER. |
||
| 17 |
address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; |
||
| 18 |
// Deterministic deployment address of the Multicall3 contract. |
||
| 19 |
address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; |
||
| 20 |
// The order of the secp256k1 curve. |
||
| 21 |
uint256 internal constant SECP256K1_ORDER = |
||
| 22 |
115792089237316195423570985008687907852837564279074904382605163141518161494337; |
||
| 23 | |||
| 24 |
uint256 internal constant UINT256_MAX = |
||
| 25 |
115792089237316195423570985008687907853269984665640564039457584007913129639935; |
||
| 26 | |||
| 27 |
Vm internal constant vm = Vm(VM_ADDRESS); |
||
| 28 |
StdStorage internal stdstore; |
||
| 29 |
} |
||
| 30 | |||
| 31 |
abstract contract TestBase is CommonBase {}
|
||
| 32 | |||
| 33 |
abstract contract ScriptBase is CommonBase {
|
||
| 34 |
VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); |
||
| 35 |
} |
||
| 36 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
// 💬 ABOUT |
||
| 5 |
// Forge Std's default Script. |
||
| 6 | |||
| 7 |
// 🧩 MODULES |
||
| 8 |
import {console} from "./console.sol";
|
||
| 9 |
import {console2} from "./console2.sol";
|
||
| 10 |
import {safeconsole} from "./safeconsole.sol";
|
||
| 11 |
import {StdChains} from "./StdChains.sol";
|
||
| 12 |
import {StdCheatsSafe} from "./StdCheats.sol";
|
||
| 13 |
import {stdJson} from "./StdJson.sol";
|
||
| 14 |
import {stdMath} from "./StdMath.sol";
|
||
| 15 |
import {StdStorage, stdStorageSafe} from "./StdStorage.sol";
|
||
| 16 |
import {StdStyle} from "./StdStyle.sol";
|
||
| 17 |
import {StdUtils} from "./StdUtils.sol";
|
||
| 18 |
import {VmSafe} from "./Vm.sol";
|
||
| 19 | |||
| 20 |
// 📦 BOILERPLATE |
||
| 21 |
import {ScriptBase} from "./Base.sol";
|
||
| 22 | |||
| 23 |
// ⭐️ SCRIPT |
||
| 24 |
abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils {
|
||
| 25 |
// Note: IS_SCRIPT() must return true. |
||
| 26 |
bool public IS_SCRIPT = true; |
||
| 27 |
} |
||
| 28 |
| Lines covered: | 0 / 31 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 |
pragma experimental ABIEncoderV2; |
||
| 4 | |||
| 5 |
import {Vm} from "./Vm.sol";
|
||
| 6 | |||
| 7 |
abstract contract StdAssertions {
|
||
| 8 |
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 9 | |||
| 10 |
event log(string); |
||
| 11 |
event logs(bytes); |
||
| 12 | |||
| 13 |
event log_address(address); |
||
| 14 |
event log_bytes32(bytes32); |
||
| 15 |
event log_int(int256); |
||
| 16 |
event log_uint(uint256); |
||
| 17 |
event log_bytes(bytes); |
||
| 18 |
event log_string(string); |
||
| 19 | |||
| 20 |
event log_named_address(string key, address val); |
||
| 21 |
event log_named_bytes32(string key, bytes32 val); |
||
| 22 |
event log_named_decimal_int(string key, int256 val, uint256 decimals); |
||
| 23 |
event log_named_decimal_uint(string key, uint256 val, uint256 decimals); |
||
| 24 |
event log_named_int(string key, int256 val); |
||
| 25 |
event log_named_uint(string key, uint256 val); |
||
| 26 |
event log_named_bytes(string key, bytes val); |
||
| 27 |
event log_named_string(string key, string val); |
||
| 28 | |||
| 29 |
event log_array(uint256[] val); |
||
| 30 |
event log_array(int256[] val); |
||
| 31 |
event log_array(address[] val); |
||
| 32 |
event log_named_array(string key, uint256[] val); |
||
| 33 |
event log_named_array(string key, int256[] val); |
||
| 34 |
event log_named_array(string key, address[] val); |
||
| 35 | |||
| 36 |
bool private _failed; |
||
| 37 | |||
| 38 |
function failed() public view returns (bool) {
|
||
| 39 |
if (_failed) {
|
||
| 40 |
return _failed; |
||
| 41 |
} else {
|
||
| 42 |
return vm.load(address(vm), bytes32("failed")) != bytes32(0);
|
||
| 43 |
} |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function fail() internal virtual {
|
||
| 47 |
vm.store(address(vm), bytes32("failed"), bytes32(uint256(1)));
|
||
| 48 |
_failed = true; |
||
| 49 |
} |
||
| 50 | |||
| 51 |
function assertTrue(bool data) internal pure virtual {
|
||
| 52 |
vm.assertTrue(data); |
||
| 53 |
} |
||
| 54 | |||
| 55 |
function assertTrue(bool data, string memory err) internal pure virtual {
|
||
| 56 |
vm.assertTrue(data, err); |
||
| 57 |
} |
||
| 58 | |||
| 59 |
function assertFalse(bool data) internal pure virtual {
|
||
| 60 |
vm.assertFalse(data); |
||
| 61 |
} |
||
| 62 | |||
| 63 |
function assertFalse(bool data, string memory err) internal pure virtual {
|
||
| 64 |
vm.assertFalse(data, err); |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function assertEq(bool left, bool right) internal pure virtual {
|
||
| 68 |
vm.assertEq(left, right); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
function assertEq(bool left, bool right, string memory err) internal pure virtual {
|
||
| 72 |
vm.assertEq(left, right, err); |
||
| 73 |
} |
||
| 74 | |||
| 75 |
function assertEq(uint256 left, uint256 right) internal pure virtual {
|
||
| 76 |
vm.assertEq(left, right); |
||
| 77 |
} |
||
| 78 | |||
| 79 |
function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual {
|
||
| 80 |
vm.assertEq(left, right, err); |
||
| 81 |
} |
||
| 82 | |||
| 83 |
function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
|
||
| 84 |
vm.assertEqDecimal(left, right, decimals); |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 88 |
vm.assertEqDecimal(left, right, decimals, err); |
||
| 89 |
} |
||
| 90 | |||
| 91 |
function assertEq(int256 left, int256 right) internal pure virtual {
|
||
| 92 |
vm.assertEq(left, right); |
||
| 93 |
} |
||
| 94 | |||
| 95 |
function assertEq(int256 left, int256 right, string memory err) internal pure virtual {
|
||
| 96 |
vm.assertEq(left, right, err); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
|
||
| 100 |
vm.assertEqDecimal(left, right, decimals); |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 104 |
vm.assertEqDecimal(left, right, decimals, err); |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function assertEq(address left, address right) internal pure virtual {
|
||
| 108 |
vm.assertEq(left, right); |
||
| 109 |
} |
||
| 110 | |||
| 111 |
function assertEq(address left, address right, string memory err) internal pure virtual {
|
||
| 112 |
vm.assertEq(left, right, err); |
||
| 113 |
} |
||
| 114 | |||
| 115 |
function assertEq(bytes32 left, bytes32 right) internal pure virtual {
|
||
| 116 |
vm.assertEq(left, right); |
||
| 117 |
} |
||
| 118 | |||
| 119 |
function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
|
||
| 120 |
vm.assertEq(left, right, err); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function assertEq32(bytes32 left, bytes32 right) internal pure virtual {
|
||
| 124 |
assertEq(left, right); |
||
| 125 |
} |
||
| 126 | |||
| 127 |
function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
|
||
| 128 |
assertEq(left, right, err); |
||
| 129 |
} |
||
| 130 | |||
| 131 |
function assertEq(string memory left, string memory right) internal pure virtual {
|
||
| 132 |
vm.assertEq(left, right); |
||
| 133 |
} |
||
| 134 | |||
| 135 |
function assertEq(string memory left, string memory right, string memory err) internal pure virtual {
|
||
| 136 |
vm.assertEq(left, right, err); |
||
| 137 |
} |
||
| 138 | |||
| 139 |
function assertEq(bytes memory left, bytes memory right) internal pure virtual {
|
||
| 140 |
vm.assertEq(left, right); |
||
| 141 |
} |
||
| 142 | |||
| 143 |
function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
|
||
| 144 |
vm.assertEq(left, right, err); |
||
| 145 |
} |
||
| 146 | |||
| 147 |
function assertEq(bool[] memory left, bool[] memory right) internal pure virtual {
|
||
| 148 |
vm.assertEq(left, right); |
||
| 149 |
} |
||
| 150 | |||
| 151 |
function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
|
||
| 152 |
vm.assertEq(left, right, err); |
||
| 153 |
} |
||
| 154 | |||
| 155 |
function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
|
||
| 156 |
vm.assertEq(left, right); |
||
| 157 |
} |
||
| 158 | |||
| 159 |
function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
|
||
| 160 |
vm.assertEq(left, right, err); |
||
| 161 |
} |
||
| 162 | |||
| 163 |
function assertEq(int256[] memory left, int256[] memory right) internal pure virtual {
|
||
| 164 |
vm.assertEq(left, right); |
||
| 165 |
} |
||
| 166 | |||
| 167 |
function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
|
||
| 168 |
vm.assertEq(left, right, err); |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function assertEq(address[] memory left, address[] memory right) internal pure virtual {
|
||
| 172 |
vm.assertEq(left, right); |
||
| 173 |
} |
||
| 174 | |||
| 175 |
function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
|
||
| 176 |
vm.assertEq(left, right, err); |
||
| 177 |
} |
||
| 178 | |||
| 179 |
function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
|
||
| 180 |
vm.assertEq(left, right); |
||
| 181 |
} |
||
| 182 | |||
| 183 |
function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
|
||
| 184 |
vm.assertEq(left, right, err); |
||
| 185 |
} |
||
| 186 | |||
| 187 |
function assertEq(string[] memory left, string[] memory right) internal pure virtual {
|
||
| 188 |
vm.assertEq(left, right); |
||
| 189 |
} |
||
| 190 | |||
| 191 |
function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
|
||
| 192 |
vm.assertEq(left, right, err); |
||
| 193 |
} |
||
| 194 | |||
| 195 |
function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
|
||
| 196 |
vm.assertEq(left, right); |
||
| 197 |
} |
||
| 198 | |||
| 199 |
function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
|
||
| 200 |
vm.assertEq(left, right, err); |
||
| 201 |
} |
||
| 202 | |||
| 203 |
// Legacy helper |
||
| 204 |
function assertEqUint(uint256 left, uint256 right) internal pure virtual {
|
||
| 205 |
assertEq(left, right); |
||
| 206 |
} |
||
| 207 | |||
| 208 |
function assertNotEq(bool left, bool right) internal pure virtual {
|
||
| 209 |
vm.assertNotEq(left, right); |
||
| 210 |
} |
||
| 211 | |||
| 212 |
function assertNotEq(bool left, bool right, string memory err) internal pure virtual {
|
||
| 213 |
vm.assertNotEq(left, right, err); |
||
| 214 |
} |
||
| 215 | |||
| 216 |
function assertNotEq(uint256 left, uint256 right) internal pure virtual {
|
||
| 217 |
vm.assertNotEq(left, right); |
||
| 218 |
} |
||
| 219 | |||
| 220 |
function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual {
|
||
| 221 |
vm.assertNotEq(left, right, err); |
||
| 222 |
} |
||
| 223 | |||
| 224 |
function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
|
||
| 225 |
vm.assertNotEqDecimal(left, right, decimals); |
||
| 226 |
} |
||
| 227 | |||
| 228 |
function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) |
||
| 229 |
internal |
||
| 230 |
pure |
||
| 231 |
virtual |
||
| 232 |
{
|
||
| 233 |
vm.assertNotEqDecimal(left, right, decimals, err); |
||
| 234 |
} |
||
| 235 | |||
| 236 |
function assertNotEq(int256 left, int256 right) internal pure virtual {
|
||
| 237 |
vm.assertNotEq(left, right); |
||
| 238 |
} |
||
| 239 | |||
| 240 |
function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual {
|
||
| 241 |
vm.assertNotEq(left, right, err); |
||
| 242 |
} |
||
| 243 | |||
| 244 |
function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
|
||
| 245 |
vm.assertNotEqDecimal(left, right, decimals); |
||
| 246 |
} |
||
| 247 | |||
| 248 |
function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 249 |
vm.assertNotEqDecimal(left, right, decimals, err); |
||
| 250 |
} |
||
| 251 | |||
| 252 |
function assertNotEq(address left, address right) internal pure virtual {
|
||
| 253 |
vm.assertNotEq(left, right); |
||
| 254 |
} |
||
| 255 | |||
| 256 |
function assertNotEq(address left, address right, string memory err) internal pure virtual {
|
||
| 257 |
vm.assertNotEq(left, right, err); |
||
| 258 |
} |
||
| 259 | |||
| 260 |
function assertNotEq(bytes32 left, bytes32 right) internal pure virtual {
|
||
| 261 |
vm.assertNotEq(left, right); |
||
| 262 |
} |
||
| 263 | |||
| 264 |
function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
|
||
| 265 |
vm.assertNotEq(left, right, err); |
||
| 266 |
} |
||
| 267 | |||
| 268 |
function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual {
|
||
| 269 |
assertNotEq(left, right); |
||
| 270 |
} |
||
| 271 | |||
| 272 |
function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
|
||
| 273 |
assertNotEq(left, right, err); |
||
| 274 |
} |
||
| 275 | |||
| 276 |
function assertNotEq(string memory left, string memory right) internal pure virtual {
|
||
| 277 |
vm.assertNotEq(left, right); |
||
| 278 |
} |
||
| 279 | |||
| 280 |
function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual {
|
||
| 281 |
vm.assertNotEq(left, right, err); |
||
| 282 |
} |
||
| 283 | |||
| 284 |
function assertNotEq(bytes memory left, bytes memory right) internal pure virtual {
|
||
| 285 |
vm.assertNotEq(left, right); |
||
| 286 |
} |
||
| 287 | |||
| 288 |
function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
|
||
| 289 |
vm.assertNotEq(left, right, err); |
||
| 290 |
} |
||
| 291 | |||
| 292 |
function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual {
|
||
| 293 |
vm.assertNotEq(left, right); |
||
| 294 |
} |
||
| 295 | |||
| 296 |
function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
|
||
| 297 |
vm.assertNotEq(left, right, err); |
||
| 298 |
} |
||
| 299 | |||
| 300 |
function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
|
||
| 301 |
vm.assertNotEq(left, right); |
||
| 302 |
} |
||
| 303 | |||
| 304 |
function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
|
||
| 305 |
vm.assertNotEq(left, right, err); |
||
| 306 |
} |
||
| 307 | |||
| 308 |
function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual {
|
||
| 309 |
vm.assertNotEq(left, right); |
||
| 310 |
} |
||
| 311 | |||
| 312 |
function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
|
||
| 313 |
vm.assertNotEq(left, right, err); |
||
| 314 |
} |
||
| 315 | |||
| 316 |
function assertNotEq(address[] memory left, address[] memory right) internal pure virtual {
|
||
| 317 |
vm.assertNotEq(left, right); |
||
| 318 |
} |
||
| 319 | |||
| 320 |
function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
|
||
| 321 |
vm.assertNotEq(left, right, err); |
||
| 322 |
} |
||
| 323 | |||
| 324 |
function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
|
||
| 325 |
vm.assertNotEq(left, right); |
||
| 326 |
} |
||
| 327 | |||
| 328 |
function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
|
||
| 329 |
vm.assertNotEq(left, right, err); |
||
| 330 |
} |
||
| 331 | |||
| 332 |
function assertNotEq(string[] memory left, string[] memory right) internal pure virtual {
|
||
| 333 |
vm.assertNotEq(left, right); |
||
| 334 |
} |
||
| 335 | |||
| 336 |
function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
|
||
| 337 |
vm.assertNotEq(left, right, err); |
||
| 338 |
} |
||
| 339 | |||
| 340 |
function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
|
||
| 341 |
vm.assertNotEq(left, right); |
||
| 342 |
} |
||
| 343 | |||
| 344 |
function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
|
||
| 345 |
vm.assertNotEq(left, right, err); |
||
| 346 |
} |
||
| 347 | |||
| 348 |
function assertLt(uint256 left, uint256 right) internal pure virtual {
|
||
| 349 |
vm.assertLt(left, right); |
||
| 350 |
} |
||
| 351 | |||
| 352 |
function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual {
|
||
| 353 |
vm.assertLt(left, right, err); |
||
| 354 |
} |
||
| 355 | |||
| 356 |
function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
|
||
| 357 |
vm.assertLtDecimal(left, right, decimals); |
||
| 358 |
} |
||
| 359 | |||
| 360 |
function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 361 |
vm.assertLtDecimal(left, right, decimals, err); |
||
| 362 |
} |
||
| 363 | |||
| 364 |
function assertLt(int256 left, int256 right) internal pure virtual {
|
||
| 365 |
vm.assertLt(left, right); |
||
| 366 |
} |
||
| 367 | |||
| 368 |
function assertLt(int256 left, int256 right, string memory err) internal pure virtual {
|
||
| 369 |
vm.assertLt(left, right, err); |
||
| 370 |
} |
||
| 371 | |||
| 372 |
function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
|
||
| 373 |
vm.assertLtDecimal(left, right, decimals); |
||
| 374 |
} |
||
| 375 | |||
| 376 |
function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 377 |
vm.assertLtDecimal(left, right, decimals, err); |
||
| 378 |
} |
||
| 379 | |||
| 380 |
function assertGt(uint256 left, uint256 right) internal pure virtual {
|
||
| 381 |
vm.assertGt(left, right); |
||
| 382 |
} |
||
| 383 | |||
| 384 |
function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual {
|
||
| 385 |
vm.assertGt(left, right, err); |
||
| 386 |
} |
||
| 387 | |||
| 388 |
function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
|
||
| 389 |
vm.assertGtDecimal(left, right, decimals); |
||
| 390 |
} |
||
| 391 | |||
| 392 |
function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 393 |
vm.assertGtDecimal(left, right, decimals, err); |
||
| 394 |
} |
||
| 395 | |||
| 396 |
function assertGt(int256 left, int256 right) internal pure virtual {
|
||
| 397 |
vm.assertGt(left, right); |
||
| 398 |
} |
||
| 399 | |||
| 400 |
function assertGt(int256 left, int256 right, string memory err) internal pure virtual {
|
||
| 401 |
vm.assertGt(left, right, err); |
||
| 402 |
} |
||
| 403 | |||
| 404 |
function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
|
||
| 405 |
vm.assertGtDecimal(left, right, decimals); |
||
| 406 |
} |
||
| 407 | |||
| 408 |
function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 409 |
vm.assertGtDecimal(left, right, decimals, err); |
||
| 410 |
} |
||
| 411 | |||
| 412 |
function assertLe(uint256 left, uint256 right) internal pure virtual {
|
||
| 413 |
vm.assertLe(left, right); |
||
| 414 |
} |
||
| 415 | |||
| 416 |
function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual {
|
||
| 417 |
vm.assertLe(left, right, err); |
||
| 418 |
} |
||
| 419 | |||
| 420 |
function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
|
||
| 421 |
vm.assertLeDecimal(left, right, decimals); |
||
| 422 |
} |
||
| 423 | |||
| 424 |
function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 425 |
vm.assertLeDecimal(left, right, decimals, err); |
||
| 426 |
} |
||
| 427 | |||
| 428 |
function assertLe(int256 left, int256 right) internal pure virtual {
|
||
| 429 |
vm.assertLe(left, right); |
||
| 430 |
} |
||
| 431 | |||
| 432 |
function assertLe(int256 left, int256 right, string memory err) internal pure virtual {
|
||
| 433 |
vm.assertLe(left, right, err); |
||
| 434 |
} |
||
| 435 | |||
| 436 |
function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
|
||
| 437 |
vm.assertLeDecimal(left, right, decimals); |
||
| 438 |
} |
||
| 439 | |||
| 440 |
function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 441 |
vm.assertLeDecimal(left, right, decimals, err); |
||
| 442 |
} |
||
| 443 | |||
| 444 |
function assertGe(uint256 left, uint256 right) internal pure virtual {
|
||
| 445 |
vm.assertGe(left, right); |
||
| 446 |
} |
||
| 447 | |||
| 448 |
function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual {
|
||
| 449 |
vm.assertGe(left, right, err); |
||
| 450 |
} |
||
| 451 | |||
| 452 |
function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
|
||
| 453 |
vm.assertGeDecimal(left, right, decimals); |
||
| 454 |
} |
||
| 455 | |||
| 456 |
function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 457 |
vm.assertGeDecimal(left, right, decimals, err); |
||
| 458 |
} |
||
| 459 | |||
| 460 |
function assertGe(int256 left, int256 right) internal pure virtual {
|
||
| 461 |
vm.assertGe(left, right); |
||
| 462 |
} |
||
| 463 | |||
| 464 |
function assertGe(int256 left, int256 right, string memory err) internal pure virtual {
|
||
| 465 |
vm.assertGe(left, right, err); |
||
| 466 |
} |
||
| 467 | |||
| 468 |
function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
|
||
| 469 |
vm.assertGeDecimal(left, right, decimals); |
||
| 470 |
} |
||
| 471 | |||
| 472 |
function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
|
||
| 473 |
vm.assertGeDecimal(left, right, decimals, err); |
||
| 474 |
} |
||
| 475 | |||
| 476 |
function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual {
|
||
| 477 |
vm.assertApproxEqAbs(left, right, maxDelta); |
||
| 478 |
} |
||
| 479 | |||
| 480 |
function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) |
||
| 481 |
internal |
||
| 482 |
pure |
||
| 483 |
virtual |
||
| 484 |
{
|
||
| 485 |
vm.assertApproxEqAbs(left, right, maxDelta, err); |
||
| 486 |
} |
||
| 487 | |||
| 488 |
function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) |
||
| 489 |
internal |
||
| 490 |
pure |
||
| 491 |
virtual |
||
| 492 |
{
|
||
| 493 |
vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); |
||
| 494 |
} |
||
| 495 | |||
| 496 |
function assertApproxEqAbsDecimal( |
||
| 497 |
uint256 left, |
||
| 498 |
uint256 right, |
||
| 499 |
uint256 maxDelta, |
||
| 500 |
uint256 decimals, |
||
| 501 |
string memory err |
||
| 502 |
) internal pure virtual {
|
||
| 503 |
vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); |
||
| 504 |
} |
||
| 505 | |||
| 506 |
function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual {
|
||
| 507 |
vm.assertApproxEqAbs(left, right, maxDelta); |
||
| 508 |
} |
||
| 509 | |||
| 510 |
function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual {
|
||
| 511 |
vm.assertApproxEqAbs(left, right, maxDelta, err); |
||
| 512 |
} |
||
| 513 | |||
| 514 |
function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) |
||
| 515 |
internal |
||
| 516 |
pure |
||
| 517 |
virtual |
||
| 518 |
{
|
||
| 519 |
vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); |
||
| 520 |
} |
||
| 521 | |||
| 522 |
function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) |
||
| 523 |
internal |
||
| 524 |
pure |
||
| 525 |
virtual |
||
| 526 |
{
|
||
| 527 |
vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); |
||
| 528 |
} |
||
| 529 | |||
| 530 |
function assertApproxEqRel( |
||
| 531 |
uint256 left, |
||
| 532 |
uint256 right, |
||
| 533 |
uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 534 |
) internal pure virtual {
|
||
| 535 |
vm.assertApproxEqRel(left, right, maxPercentDelta); |
||
| 536 |
} |
||
| 537 | |||
| 538 |
function assertApproxEqRel( |
||
| 539 |
uint256 left, |
||
| 540 |
uint256 right, |
||
| 541 |
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 542 |
string memory err |
||
| 543 |
) internal pure virtual {
|
||
| 544 |
vm.assertApproxEqRel(left, right, maxPercentDelta, err); |
||
| 545 |
} |
||
| 546 | |||
| 547 |
function assertApproxEqRelDecimal( |
||
| 548 |
uint256 left, |
||
| 549 |
uint256 right, |
||
| 550 |
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 551 |
uint256 decimals |
||
| 552 |
) internal pure virtual {
|
||
| 553 |
vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); |
||
| 554 |
} |
||
| 555 | |||
| 556 |
function assertApproxEqRelDecimal( |
||
| 557 |
uint256 left, |
||
| 558 |
uint256 right, |
||
| 559 |
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 560 |
uint256 decimals, |
||
| 561 |
string memory err |
||
| 562 |
) internal pure virtual {
|
||
| 563 |
vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); |
||
| 564 |
} |
||
| 565 | |||
| 566 |
function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual {
|
||
| 567 |
vm.assertApproxEqRel(left, right, maxPercentDelta); |
||
| 568 |
} |
||
| 569 | |||
| 570 |
function assertApproxEqRel( |
||
| 571 |
int256 left, |
||
| 572 |
int256 right, |
||
| 573 |
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 574 |
string memory err |
||
| 575 |
) internal pure virtual {
|
||
| 576 |
vm.assertApproxEqRel(left, right, maxPercentDelta, err); |
||
| 577 |
} |
||
| 578 | |||
| 579 |
function assertApproxEqRelDecimal( |
||
| 580 |
int256 left, |
||
| 581 |
int256 right, |
||
| 582 |
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 583 |
uint256 decimals |
||
| 584 |
) internal pure virtual {
|
||
| 585 |
vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); |
||
| 586 |
} |
||
| 587 | |||
| 588 |
function assertApproxEqRelDecimal( |
||
| 589 |
int256 left, |
||
| 590 |
int256 right, |
||
| 591 |
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% |
||
| 592 |
uint256 decimals, |
||
| 593 |
string memory err |
||
| 594 |
) internal pure virtual {
|
||
| 595 |
vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); |
||
| 596 |
} |
||
| 597 | |||
| 598 |
// Inherited from DSTest, not used but kept for backwards-compatibility |
||
| 599 |
function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) {
|
||
| 600 |
return keccak256(left) == keccak256(right); |
||
| 601 |
} |
||
| 602 | |||
| 603 |
function assertEq0(bytes memory left, bytes memory right) internal pure virtual {
|
||
| 604 |
assertEq(left, right); |
||
| 605 |
} |
||
| 606 | |||
| 607 |
function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
|
||
| 608 |
assertEq(left, right, err); |
||
| 609 |
} |
||
| 610 | |||
| 611 |
function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual {
|
||
| 612 |
assertNotEq(left, right); |
||
| 613 |
} |
||
| 614 | |||
| 615 |
function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
|
||
| 616 |
assertNotEq(left, right, err); |
||
| 617 |
} |
||
| 618 | |||
| 619 |
function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {
|
||
| 620 |
assertEqCall(target, callDataA, target, callDataB, true); |
||
| 621 |
} |
||
| 622 | |||
| 623 |
function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) |
||
| 624 |
internal |
||
| 625 |
virtual |
||
| 626 |
{
|
||
| 627 |
assertEqCall(targetA, callDataA, targetB, callDataB, true); |
||
| 628 |
} |
||
| 629 | |||
| 630 |
function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) |
||
| 631 |
internal |
||
| 632 |
virtual |
||
| 633 |
{
|
||
| 634 |
assertEqCall(target, callDataA, target, callDataB, strictRevertData); |
||
| 635 |
} |
||
| 636 | |||
| 637 |
function assertEqCall( |
||
| 638 |
address targetA, |
||
| 639 |
bytes memory callDataA, |
||
| 640 |
address targetB, |
||
| 641 |
bytes memory callDataB, |
||
| 642 |
bool strictRevertData |
||
| 643 |
) internal virtual {
|
||
| 644 |
(bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); |
||
| 645 |
(bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); |
||
| 646 | |||
| 647 |
if (successA && successB) {
|
||
| 648 |
assertEq(returnDataA, returnDataB, "Call return data does not match"); |
||
| 649 |
} |
||
| 650 | |||
| 651 |
if (!successA && !successB && strictRevertData) {
|
||
| 652 |
assertEq(returnDataA, returnDataB, "Call revert data does not match"); |
||
| 653 |
} |
||
| 654 | |||
| 655 |
if (!successA && successB) {
|
||
| 656 |
emit log("Error: Calls were not equal");
|
||
| 657 |
emit log_named_bytes(" Left call revert data", returnDataA);
|
||
| 658 |
emit log_named_bytes(" Right call return data", returnDataB);
|
||
| 659 |
revert("assertion failed");
|
||
| 660 |
} |
||
| 661 | |||
| 662 |
if (successA && !successB) {
|
||
| 663 |
emit log("Error: Calls were not equal");
|
||
| 664 |
emit log_named_bytes(" Left call return data", returnDataA);
|
||
| 665 |
emit log_named_bytes(" Right call revert data", returnDataB);
|
||
| 666 |
revert("assertion failed");
|
||
| 667 |
} |
||
| 668 |
} |
||
| 669 |
} |
||
| 670 |
| Lines covered: | 1 / 1 (100.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
import {VmSafe} from "./Vm.sol";
|
||
| 5 | |||
| 6 |
/** |
||
| 7 |
* StdChains provides information about EVM compatible chains that can be used in scripts/tests. |
||
| 8 |
* For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are |
||
| 9 |
* identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of |
||
| 10 |
* the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the |
||
| 11 |
* alias used in this contract, which can be found as the first argument to the |
||
| 12 |
* `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. |
||
| 13 |
* |
||
| 14 |
* There are two main ways to use this contract: |
||
| 15 |
* 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or |
||
| 16 |
* `setChain(string memory chainAlias, Chain memory chain)` |
||
| 17 |
* 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. |
||
| 18 |
* |
||
| 19 |
* The first time either of those are used, chains are initialized with the default set of RPC URLs. |
||
| 20 |
* This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in |
||
| 21 |
* `defaultRpcUrls`. |
||
| 22 |
* |
||
| 23 |
* The `setChain` function is straightforward, and it simply saves off the given chain data. |
||
| 24 |
* |
||
| 25 |
* The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say |
||
| 26 |
* we want to retrieve the RPC URL for `mainnet`: |
||
| 27 |
* - If you have specified data with `setChain`, it will return that. |
||
| 28 |
* - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it |
||
| 29 |
* is valid (e.g. a URL is specified, or an environment variable is given and exists). |
||
| 30 |
* - If neither of the above conditions is met, the default data is returned. |
||
| 31 |
* |
||
| 32 |
* Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. |
||
| 33 |
*/ |
||
| 34 |
abstract contract StdChains {
|
||
| 35 |
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 36 | |||
| 37 |
bool private stdChainsInitialized; |
||
| 38 | |||
| 39 |
struct ChainData {
|
||
| 40 |
string name; |
||
| 41 |
uint256 chainId; |
||
| 42 |
string rpcUrl; |
||
| 43 |
} |
||
| 44 | |||
| 45 |
struct Chain {
|
||
| 46 |
// The chain name. |
||
| 47 |
string name; |
||
| 48 |
// The chain's Chain ID. |
||
| 49 |
uint256 chainId; |
||
| 50 |
// The chain's alias. (i.e. what gets specified in `foundry.toml`). |
||
| 51 |
string chainAlias; |
||
| 52 |
// A default RPC endpoint for this chain. |
||
| 53 |
// NOTE: This default RPC URL is included for convenience to facilitate quick tests and |
||
| 54 |
// experimentation. Do not use this RPC URL for production test suites, CI, or other heavy |
||
| 55 |
// usage as you will be throttled and this is a disservice to others who need this endpoint. |
||
| 56 |
string rpcUrl; |
||
| 57 |
} |
||
| 58 | |||
| 59 |
// Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. |
||
| 60 |
mapping(string => Chain) private chains; |
||
| 61 |
// Maps from the chain's alias to it's default RPC URL. |
||
| 62 |
mapping(string => string) private defaultRpcUrls; |
||
| 63 |
// Maps from a chain ID to it's alias. |
||
| 64 |
mapping(uint256 => string) private idToAlias; |
||
| 65 | |||
| 66 |
√ 3
|
bool private fallbackToDefaultRpcUrls = true; |
|
| 67 | |||
| 68 |
// The RPC URL will be fetched from config or defaultRpcUrls if possible. |
||
| 69 |
function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
|
||
| 70 |
require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); |
||
| 71 | |||
| 72 |
initializeStdChains(); |
||
| 73 |
chain = chains[chainAlias]; |
||
| 74 |
require( |
||
| 75 |
chain.chainId != 0, |
||
| 76 |
string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
|
||
| 77 |
); |
||
| 78 | |||
| 79 |
chain = getChainWithUpdatedRpcUrl(chainAlias, chain); |
||
| 80 |
} |
||
| 81 | |||
| 82 |
function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
|
||
| 83 |
require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); |
||
| 84 |
initializeStdChains(); |
||
| 85 |
string memory chainAlias = idToAlias[chainId]; |
||
| 86 | |||
| 87 |
chain = chains[chainAlias]; |
||
| 88 | |||
| 89 |
require( |
||
| 90 |
chain.chainId != 0, |
||
| 91 |
string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
|
||
| 92 |
); |
||
| 93 | |||
| 94 |
chain = getChainWithUpdatedRpcUrl(chainAlias, chain); |
||
| 95 |
} |
||
| 96 | |||
| 97 |
// set chain info, with priority to argument's rpcUrl field. |
||
| 98 |
function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
|
||
| 99 |
require( |
||
| 100 |
bytes(chainAlias).length != 0, |
||
| 101 |
"StdChains setChain(string,ChainData): Chain alias cannot be the empty string." |
||
| 102 |
); |
||
| 103 | |||
| 104 |
require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); |
||
| 105 | |||
| 106 |
initializeStdChains(); |
||
| 107 |
string memory foundAlias = idToAlias[chain.chainId]; |
||
| 108 | |||
| 109 |
require( |
||
| 110 |
bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), |
||
| 111 |
string( |
||
| 112 |
abi.encodePacked( |
||
| 113 |
"StdChains setChain(string,ChainData): Chain ID ", |
||
| 114 |
vm.toString(chain.chainId), |
||
| 115 |
" already used by \"", |
||
| 116 |
foundAlias, |
||
| 117 |
"\"." |
||
| 118 |
) |
||
| 119 |
) |
||
| 120 |
); |
||
| 121 | |||
| 122 |
uint256 oldChainId = chains[chainAlias].chainId; |
||
| 123 |
delete idToAlias[oldChainId]; |
||
| 124 | |||
| 125 |
chains[chainAlias] = |
||
| 126 |
Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
|
||
| 127 |
idToAlias[chain.chainId] = chainAlias; |
||
| 128 |
} |
||
| 129 | |||
| 130 |
// set chain info, with priority to argument's rpcUrl field. |
||
| 131 |
function setChain(string memory chainAlias, Chain memory chain) internal virtual {
|
||
| 132 |
setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
|
||
| 133 |
} |
||
| 134 | |||
| 135 |
function _toUpper(string memory str) private pure returns (string memory) {
|
||
| 136 |
bytes memory strb = bytes(str); |
||
| 137 |
bytes memory copy = new bytes(strb.length); |
||
| 138 |
for (uint256 i = 0; i < strb.length; i++) {
|
||
| 139 |
bytes1 b = strb[i]; |
||
| 140 |
if (b >= 0x61 && b <= 0x7A) {
|
||
| 141 |
copy[i] = bytes1(uint8(b) - 32); |
||
| 142 |
} else {
|
||
| 143 |
copy[i] = b; |
||
| 144 |
} |
||
| 145 |
} |
||
| 146 |
return string(copy); |
||
| 147 |
} |
||
| 148 | |||
| 149 |
// lookup rpcUrl, in descending order of priority: |
||
| 150 |
// current -> config (foundry.toml) -> environment variable -> default |
||
| 151 |
function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) |
||
| 152 |
private |
||
| 153 |
view |
||
| 154 |
returns (Chain memory) |
||
| 155 |
{
|
||
| 156 |
if (bytes(chain.rpcUrl).length == 0) {
|
||
| 157 |
try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
|
||
| 158 |
chain.rpcUrl = configRpcUrl; |
||
| 159 |
} catch (bytes memory err) {
|
||
| 160 |
string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); |
||
| 161 |
if (fallbackToDefaultRpcUrls) {
|
||
| 162 |
chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); |
||
| 163 |
} else {
|
||
| 164 |
chain.rpcUrl = vm.envString(envName); |
||
| 165 |
} |
||
| 166 |
// Distinguish 'not found' from 'cannot read' |
||
| 167 |
// The upstream error thrown by forge for failing cheats changed so we check both the old and new versions |
||
| 168 |
bytes memory oldNotFoundError = |
||
| 169 |
abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
|
||
| 170 |
bytes memory newNotFoundError = abi.encodeWithSignature( |
||
| 171 |
"CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
|
||
| 172 |
); |
||
| 173 |
bytes32 errHash = keccak256(err); |
||
| 174 |
if ( |
||
| 175 |
(errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) |
||
| 176 |
|| bytes(chain.rpcUrl).length == 0 |
||
| 177 |
) {
|
||
| 178 |
/// @solidity memory-safe-assembly |
||
| 179 |
assembly {
|
||
| 180 |
revert(add(32, err), mload(err)) |
||
| 181 |
} |
||
| 182 |
} |
||
| 183 |
} |
||
| 184 |
} |
||
| 185 |
return chain; |
||
| 186 |
} |
||
| 187 | |||
| 188 |
function setFallbackToDefaultRpcUrls(bool useDefault) internal {
|
||
| 189 |
fallbackToDefaultRpcUrls = useDefault; |
||
| 190 |
} |
||
| 191 | |||
| 192 |
function initializeStdChains() private {
|
||
| 193 |
if (stdChainsInitialized) return; |
||
| 194 | |||
| 195 |
stdChainsInitialized = true; |
||
| 196 | |||
| 197 |
// If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` |
||
| 198 |
setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
|
||
| 199 |
setChainWithDefaultRpcUrl( |
||
| 200 |
"mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP")
|
||
| 201 |
); |
||
| 202 |
setChainWithDefaultRpcUrl( |
||
| 203 |
"sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
|
||
| 204 |
); |
||
| 205 |
setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
|
||
| 206 |
setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
|
||
| 207 |
setChainWithDefaultRpcUrl( |
||
| 208 |
"optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
|
||
| 209 |
); |
||
| 210 |
setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
|
||
| 211 |
setChainWithDefaultRpcUrl( |
||
| 212 |
"arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
|
||
| 213 |
); |
||
| 214 |
setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
|
||
| 215 |
setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
|
||
| 216 |
setChainWithDefaultRpcUrl( |
||
| 217 |
"polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
|
||
| 218 |
); |
||
| 219 |
setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
|
||
| 220 |
setChainWithDefaultRpcUrl( |
||
| 221 |
"avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
|
||
| 222 |
); |
||
| 223 |
setChainWithDefaultRpcUrl( |
||
| 224 |
"bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
|
||
| 225 |
); |
||
| 226 |
setChainWithDefaultRpcUrl( |
||
| 227 |
"bnb_smart_chain_testnet", |
||
| 228 |
ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
|
||
| 229 |
); |
||
| 230 |
setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
|
||
| 231 |
setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
|
||
| 232 |
setChainWithDefaultRpcUrl( |
||
| 233 |
"moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
|
||
| 234 |
); |
||
| 235 |
setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
|
||
| 236 |
setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
|
||
| 237 |
setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
|
||
| 238 |
setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io"));
|
||
| 239 |
setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io"));
|
||
| 240 |
setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/"));
|
||
| 241 |
setChainWithDefaultRpcUrl( |
||
| 242 |
"fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/")
|
||
| 243 |
); |
||
| 244 |
setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
|
||
| 245 |
setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
|
||
| 246 |
setChainWithDefaultRpcUrl( |
||
| 247 |
"berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com")
|
||
| 248 |
); |
||
| 249 |
} |
||
| 250 | |||
| 251 |
// set chain info, with priority to chainAlias' rpc url in foundry.toml |
||
| 252 |
function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
|
||
| 253 |
string memory rpcUrl = chain.rpcUrl; |
||
| 254 |
defaultRpcUrls[chainAlias] = rpcUrl; |
||
| 255 |
chain.rpcUrl = ""; |
||
| 256 |
setChain(chainAlias, chain); |
||
| 257 |
chain.rpcUrl = rpcUrl; // restore argument |
||
| 258 |
} |
||
| 259 |
} |
||
| 260 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
import {StdStorage, stdStorage} from "./StdStorage.sol";
|
||
| 7 |
import {console2} from "./console2.sol";
|
||
| 8 |
import {Vm} from "./Vm.sol";
|
||
| 9 | |||
| 10 |
abstract contract StdCheatsSafe {
|
||
| 11 |
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 12 | |||
| 13 |
uint256 private constant UINT256_MAX = |
||
| 14 |
115792089237316195423570985008687907853269984665640564039457584007913129639935; |
||
| 15 | |||
| 16 |
bool private gasMeteringOff; |
||
| 17 | |||
| 18 |
// Data structures to parse Transaction objects from the broadcast artifact |
||
| 19 |
// that conform to EIP1559. The Raw structs is what is parsed from the JSON |
||
| 20 |
// and then converted to the one that is used by the user for better UX. |
||
| 21 | |||
| 22 |
struct RawTx1559 {
|
||
| 23 |
string[] arguments; |
||
| 24 |
address contractAddress; |
||
| 25 |
string contractName; |
||
| 26 |
// json value name = function |
||
| 27 |
string functionSig; |
||
| 28 |
bytes32 hash; |
||
| 29 |
// json value name = tx |
||
| 30 |
RawTx1559Detail txDetail; |
||
| 31 |
// json value name = type |
||
| 32 |
string opcode; |
||
| 33 |
} |
||
| 34 | |||
| 35 |
struct RawTx1559Detail {
|
||
| 36 |
AccessList[] accessList; |
||
| 37 |
bytes data; |
||
| 38 |
address from; |
||
| 39 |
bytes gas; |
||
| 40 |
bytes nonce; |
||
| 41 |
address to; |
||
| 42 |
bytes txType; |
||
| 43 |
bytes value; |
||
| 44 |
} |
||
| 45 | |||
| 46 |
struct Tx1559 {
|
||
| 47 |
string[] arguments; |
||
| 48 |
address contractAddress; |
||
| 49 |
string contractName; |
||
| 50 |
string functionSig; |
||
| 51 |
bytes32 hash; |
||
| 52 |
Tx1559Detail txDetail; |
||
| 53 |
string opcode; |
||
| 54 |
} |
||
| 55 | |||
| 56 |
struct Tx1559Detail {
|
||
| 57 |
AccessList[] accessList; |
||
| 58 |
bytes data; |
||
| 59 |
address from; |
||
| 60 |
uint256 gas; |
||
| 61 |
uint256 nonce; |
||
| 62 |
address to; |
||
| 63 |
uint256 txType; |
||
| 64 |
uint256 value; |
||
| 65 |
} |
||
| 66 | |||
| 67 |
// Data structures to parse Transaction objects from the broadcast artifact |
||
| 68 |
// that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON |
||
| 69 |
// and then converted to the one that is used by the user for better UX. |
||
| 70 | |||
| 71 |
struct TxLegacy {
|
||
| 72 |
string[] arguments; |
||
| 73 |
address contractAddress; |
||
| 74 |
string contractName; |
||
| 75 |
string functionSig; |
||
| 76 |
string hash; |
||
| 77 |
string opcode; |
||
| 78 |
TxDetailLegacy transaction; |
||
| 79 |
} |
||
| 80 | |||
| 81 |
struct TxDetailLegacy {
|
||
| 82 |
AccessList[] accessList; |
||
| 83 |
uint256 chainId; |
||
| 84 |
bytes data; |
||
| 85 |
address from; |
||
| 86 |
uint256 gas; |
||
| 87 |
uint256 gasPrice; |
||
| 88 |
bytes32 hash; |
||
| 89 |
uint256 nonce; |
||
| 90 |
bytes1 opcode; |
||
| 91 |
bytes32 r; |
||
| 92 |
bytes32 s; |
||
| 93 |
uint256 txType; |
||
| 94 |
address to; |
||
| 95 |
uint8 v; |
||
| 96 |
uint256 value; |
||
| 97 |
} |
||
| 98 | |||
| 99 |
struct AccessList {
|
||
| 100 |
address accessAddress; |
||
| 101 |
bytes32[] storageKeys; |
||
| 102 |
} |
||
| 103 | |||
| 104 |
// Data structures to parse Receipt objects from the broadcast artifact. |
||
| 105 |
// The Raw structs is what is parsed from the JSON |
||
| 106 |
// and then converted to the one that is used by the user for better UX. |
||
| 107 | |||
| 108 |
struct RawReceipt {
|
||
| 109 |
bytes32 blockHash; |
||
| 110 |
bytes blockNumber; |
||
| 111 |
address contractAddress; |
||
| 112 |
bytes cumulativeGasUsed; |
||
| 113 |
bytes effectiveGasPrice; |
||
| 114 |
address from; |
||
| 115 |
bytes gasUsed; |
||
| 116 |
RawReceiptLog[] logs; |
||
| 117 |
bytes logsBloom; |
||
| 118 |
bytes status; |
||
| 119 |
address to; |
||
| 120 |
bytes32 transactionHash; |
||
| 121 |
bytes transactionIndex; |
||
| 122 |
} |
||
| 123 | |||
| 124 |
struct Receipt {
|
||
| 125 |
bytes32 blockHash; |
||
| 126 |
uint256 blockNumber; |
||
| 127 |
address contractAddress; |
||
| 128 |
uint256 cumulativeGasUsed; |
||
| 129 |
uint256 effectiveGasPrice; |
||
| 130 |
address from; |
||
| 131 |
uint256 gasUsed; |
||
| 132 |
ReceiptLog[] logs; |
||
| 133 |
bytes logsBloom; |
||
| 134 |
uint256 status; |
||
| 135 |
address to; |
||
| 136 |
bytes32 transactionHash; |
||
| 137 |
uint256 transactionIndex; |
||
| 138 |
} |
||
| 139 | |||
| 140 |
// Data structures to parse the entire broadcast artifact, assuming the |
||
| 141 |
// transactions conform to EIP1559. |
||
| 142 | |||
| 143 |
struct EIP1559ScriptArtifact {
|
||
| 144 |
string[] libraries; |
||
| 145 |
string path; |
||
| 146 |
string[] pending; |
||
| 147 |
Receipt[] receipts; |
||
| 148 |
uint256 timestamp; |
||
| 149 |
Tx1559[] transactions; |
||
| 150 |
TxReturn[] txReturns; |
||
| 151 |
} |
||
| 152 | |||
| 153 |
struct RawEIP1559ScriptArtifact {
|
||
| 154 |
string[] libraries; |
||
| 155 |
string path; |
||
| 156 |
string[] pending; |
||
| 157 |
RawReceipt[] receipts; |
||
| 158 |
TxReturn[] txReturns; |
||
| 159 |
uint256 timestamp; |
||
| 160 |
RawTx1559[] transactions; |
||
| 161 |
} |
||
| 162 | |||
| 163 |
struct RawReceiptLog {
|
||
| 164 |
// json value = address |
||
| 165 |
address logAddress; |
||
| 166 |
bytes32 blockHash; |
||
| 167 |
bytes blockNumber; |
||
| 168 |
bytes data; |
||
| 169 |
bytes logIndex; |
||
| 170 |
bool removed; |
||
| 171 |
bytes32[] topics; |
||
| 172 |
bytes32 transactionHash; |
||
| 173 |
bytes transactionIndex; |
||
| 174 |
bytes transactionLogIndex; |
||
| 175 |
} |
||
| 176 | |||
| 177 |
struct ReceiptLog {
|
||
| 178 |
// json value = address |
||
| 179 |
address logAddress; |
||
| 180 |
bytes32 blockHash; |
||
| 181 |
uint256 blockNumber; |
||
| 182 |
bytes data; |
||
| 183 |
uint256 logIndex; |
||
| 184 |
bytes32[] topics; |
||
| 185 |
uint256 transactionIndex; |
||
| 186 |
uint256 transactionLogIndex; |
||
| 187 |
bool removed; |
||
| 188 |
} |
||
| 189 | |||
| 190 |
struct TxReturn {
|
||
| 191 |
string internalType; |
||
| 192 |
string value; |
||
| 193 |
} |
||
| 194 | |||
| 195 |
struct Account {
|
||
| 196 |
address addr; |
||
| 197 |
uint256 key; |
||
| 198 |
} |
||
| 199 | |||
| 200 |
enum AddressType {
|
||
| 201 |
Payable, |
||
| 202 |
NonPayable, |
||
| 203 |
ZeroAddress, |
||
| 204 |
Precompile, |
||
| 205 |
ForgeAddress |
||
| 206 |
} |
||
| 207 | |||
| 208 |
// Checks that `addr` is not blacklisted by token contracts that have a blacklist. |
||
| 209 |
function assumeNotBlacklisted(address token, address addr) internal view virtual {
|
||
| 210 |
// Nothing to check if `token` is not a contract. |
||
| 211 |
uint256 tokenCodeSize; |
||
| 212 |
assembly {
|
||
| 213 |
tokenCodeSize := extcodesize(token) |
||
| 214 |
} |
||
| 215 |
require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); |
||
| 216 | |||
| 217 |
bool success; |
||
| 218 |
bytes memory returnData; |
||
| 219 | |||
| 220 |
// 4-byte selector for `isBlacklisted(address)`, used by USDC. |
||
| 221 |
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr)); |
||
| 222 |
vm.assume(!success || abi.decode(returnData, (bool)) == false); |
||
| 223 | |||
| 224 |
// 4-byte selector for `isBlackListed(address)`, used by USDT. |
||
| 225 |
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr)); |
||
| 226 |
vm.assume(!success || abi.decode(returnData, (bool)) == false); |
||
| 227 |
} |
||
| 228 | |||
| 229 |
// Checks that `addr` is not blacklisted by token contracts that have a blacklist. |
||
| 230 |
// This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for |
||
| 231 |
// backwards compatibility, since this name was used in the original PR which has already has |
||
| 232 |
// a release. This function can be removed in a future release once we want a breaking change. |
||
| 233 |
function assumeNoBlacklisted(address token, address addr) internal view virtual {
|
||
| 234 |
assumeNotBlacklisted(token, addr); |
||
| 235 |
} |
||
| 236 | |||
| 237 |
function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
|
||
| 238 |
if (addressType == AddressType.Payable) {
|
||
| 239 |
assumeNotPayable(addr); |
||
| 240 |
} else if (addressType == AddressType.NonPayable) {
|
||
| 241 |
assumePayable(addr); |
||
| 242 |
} else if (addressType == AddressType.ZeroAddress) {
|
||
| 243 |
assumeNotZeroAddress(addr); |
||
| 244 |
} else if (addressType == AddressType.Precompile) {
|
||
| 245 |
assumeNotPrecompile(addr); |
||
| 246 |
} else if (addressType == AddressType.ForgeAddress) {
|
||
| 247 |
assumeNotForgeAddress(addr); |
||
| 248 |
} |
||
| 249 |
} |
||
| 250 | |||
| 251 |
function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
|
||
| 252 |
assumeAddressIsNot(addr, addressType1); |
||
| 253 |
assumeAddressIsNot(addr, addressType2); |
||
| 254 |
} |
||
| 255 | |||
| 256 |
function assumeAddressIsNot( |
||
| 257 |
address addr, |
||
| 258 |
AddressType addressType1, |
||
| 259 |
AddressType addressType2, |
||
| 260 |
AddressType addressType3 |
||
| 261 |
) internal virtual {
|
||
| 262 |
assumeAddressIsNot(addr, addressType1); |
||
| 263 |
assumeAddressIsNot(addr, addressType2); |
||
| 264 |
assumeAddressIsNot(addr, addressType3); |
||
| 265 |
} |
||
| 266 | |||
| 267 |
function assumeAddressIsNot( |
||
| 268 |
address addr, |
||
| 269 |
AddressType addressType1, |
||
| 270 |
AddressType addressType2, |
||
| 271 |
AddressType addressType3, |
||
| 272 |
AddressType addressType4 |
||
| 273 |
) internal virtual {
|
||
| 274 |
assumeAddressIsNot(addr, addressType1); |
||
| 275 |
assumeAddressIsNot(addr, addressType2); |
||
| 276 |
assumeAddressIsNot(addr, addressType3); |
||
| 277 |
assumeAddressIsNot(addr, addressType4); |
||
| 278 |
} |
||
| 279 | |||
| 280 |
// This function checks whether an address, `addr`, is payable. It works by sending 1 wei to |
||
| 281 |
// `addr` and checking the `success` return value. |
||
| 282 |
// NOTE: This function may result in state changes depending on the fallback/receive logic |
||
| 283 |
// implemented by `addr`, which should be taken into account when this function is used. |
||
| 284 |
function _isPayable(address addr) private returns (bool) {
|
||
| 285 |
require( |
||
| 286 |
addr.balance < UINT256_MAX, |
||
| 287 |
"StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" |
||
| 288 |
); |
||
| 289 |
uint256 origBalanceTest = address(this).balance; |
||
| 290 |
uint256 origBalanceAddr = address(addr).balance; |
||
| 291 | |||
| 292 |
vm.deal(address(this), 1); |
||
| 293 |
(bool success,) = payable(addr).call{value: 1}("");
|
||
| 294 | |||
| 295 |
// reset balances |
||
| 296 |
vm.deal(address(this), origBalanceTest); |
||
| 297 |
vm.deal(addr, origBalanceAddr); |
||
| 298 | |||
| 299 |
return success; |
||
| 300 |
} |
||
| 301 | |||
| 302 |
// NOTE: This function may result in state changes depending on the fallback/receive logic |
||
| 303 |
// implemented by `addr`, which should be taken into account when this function is used. See the |
||
| 304 |
// `_isPayable` method for more information. |
||
| 305 |
function assumePayable(address addr) internal virtual {
|
||
| 306 |
vm.assume(_isPayable(addr)); |
||
| 307 |
} |
||
| 308 | |||
| 309 |
function assumeNotPayable(address addr) internal virtual {
|
||
| 310 |
vm.assume(!_isPayable(addr)); |
||
| 311 |
} |
||
| 312 | |||
| 313 |
function assumeNotZeroAddress(address addr) internal pure virtual {
|
||
| 314 |
vm.assume(addr != address(0)); |
||
| 315 |
} |
||
| 316 | |||
| 317 |
function assumeNotPrecompile(address addr) internal pure virtual {
|
||
| 318 |
assumeNotPrecompile(addr, _pureChainId()); |
||
| 319 |
} |
||
| 320 | |||
| 321 |
function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
|
||
| 322 |
// Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific |
||
| 323 |
// address), but the same rationale for excluding them applies so we include those too. |
||
| 324 | |||
| 325 |
// These are reserved by Ethereum and may be on all EVM-compatible chains. |
||
| 326 |
vm.assume(addr < address(0x1) || addr > address(0xff)); |
||
| 327 | |||
| 328 |
// forgefmt: disable-start |
||
| 329 |
if (chainId == 10 || chainId == 420) {
|
||
| 330 |
// https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 |
||
| 331 |
vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); |
||
| 332 |
} else if (chainId == 42161 || chainId == 421613) {
|
||
| 333 |
// https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains |
||
| 334 |
vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068)); |
||
| 335 |
} else if (chainId == 43114 || chainId == 43113) {
|
||
| 336 |
// https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59 |
||
| 337 |
vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff)); |
||
| 338 |
vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF)); |
||
| 339 |
vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff)); |
||
| 340 |
} |
||
| 341 |
// forgefmt: disable-end |
||
| 342 |
} |
||
| 343 | |||
| 344 |
function assumeNotForgeAddress(address addr) internal pure virtual {
|
||
| 345 |
// vm, console, and Create2Deployer addresses |
||
| 346 |
vm.assume( |
||
| 347 |
addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67 |
||
| 348 |
&& addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C |
||
| 349 |
); |
||
| 350 |
} |
||
| 351 | |||
| 352 |
function readEIP1559ScriptArtifact(string memory path) |
||
| 353 |
internal |
||
| 354 |
view |
||
| 355 |
virtual |
||
| 356 |
returns (EIP1559ScriptArtifact memory) |
||
| 357 |
{
|
||
| 358 |
string memory data = vm.readFile(path); |
||
| 359 |
bytes memory parsedData = vm.parseJson(data); |
||
| 360 |
RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact)); |
||
| 361 |
EIP1559ScriptArtifact memory artifact; |
||
| 362 |
artifact.libraries = rawArtifact.libraries; |
||
| 363 |
artifact.path = rawArtifact.path; |
||
| 364 |
artifact.timestamp = rawArtifact.timestamp; |
||
| 365 |
artifact.pending = rawArtifact.pending; |
||
| 366 |
artifact.txReturns = rawArtifact.txReturns; |
||
| 367 |
artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts); |
||
| 368 |
artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions); |
||
| 369 |
return artifact; |
||
| 370 |
} |
||
| 371 | |||
| 372 |
function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
|
||
| 373 |
Tx1559[] memory txs = new Tx1559[](rawTxs.length); |
||
| 374 |
for (uint256 i; i < rawTxs.length; i++) {
|
||
| 375 |
txs[i] = rawToConvertedEIPTx1559(rawTxs[i]); |
||
| 376 |
} |
||
| 377 |
return txs; |
||
| 378 |
} |
||
| 379 | |||
| 380 |
function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
|
||
| 381 |
Tx1559 memory transaction; |
||
| 382 |
transaction.arguments = rawTx.arguments; |
||
| 383 |
transaction.contractName = rawTx.contractName; |
||
| 384 |
transaction.functionSig = rawTx.functionSig; |
||
| 385 |
transaction.hash = rawTx.hash; |
||
| 386 |
transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail); |
||
| 387 |
transaction.opcode = rawTx.opcode; |
||
| 388 |
return transaction; |
||
| 389 |
} |
||
| 390 | |||
| 391 |
function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) |
||
| 392 |
internal |
||
| 393 |
pure |
||
| 394 |
virtual |
||
| 395 |
returns (Tx1559Detail memory) |
||
| 396 |
{
|
||
| 397 |
Tx1559Detail memory txDetail; |
||
| 398 |
txDetail.data = rawDetail.data; |
||
| 399 |
txDetail.from = rawDetail.from; |
||
| 400 |
txDetail.to = rawDetail.to; |
||
| 401 |
txDetail.nonce = _bytesToUint(rawDetail.nonce); |
||
| 402 |
txDetail.txType = _bytesToUint(rawDetail.txType); |
||
| 403 |
txDetail.value = _bytesToUint(rawDetail.value); |
||
| 404 |
txDetail.gas = _bytesToUint(rawDetail.gas); |
||
| 405 |
txDetail.accessList = rawDetail.accessList; |
||
| 406 |
return txDetail; |
||
| 407 |
} |
||
| 408 | |||
| 409 |
function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
|
||
| 410 |
string memory deployData = vm.readFile(path); |
||
| 411 |
bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); |
||
| 412 |
RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[])); |
||
| 413 |
return rawToConvertedEIPTx1559s(rawTxs); |
||
| 414 |
} |
||
| 415 | |||
| 416 |
function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
|
||
| 417 |
string memory deployData = vm.readFile(path); |
||
| 418 |
string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
|
||
| 419 |
bytes memory parsedDeployData = vm.parseJson(deployData, key); |
||
| 420 |
RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559)); |
||
| 421 |
return rawToConvertedEIPTx1559(rawTx); |
||
| 422 |
} |
||
| 423 | |||
| 424 |
// Analogous to readTransactions, but for receipts. |
||
| 425 |
function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
|
||
| 426 |
string memory deployData = vm.readFile(path); |
||
| 427 |
bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); |
||
| 428 |
RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[])); |
||
| 429 |
return rawToConvertedReceipts(rawReceipts); |
||
| 430 |
} |
||
| 431 | |||
| 432 |
function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
|
||
| 433 |
string memory deployData = vm.readFile(path); |
||
| 434 |
string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
|
||
| 435 |
bytes memory parsedDeployData = vm.parseJson(deployData, key); |
||
| 436 |
RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt)); |
||
| 437 |
return rawToConvertedReceipt(rawReceipt); |
||
| 438 |
} |
||
| 439 | |||
| 440 |
function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
|
||
| 441 |
Receipt[] memory receipts = new Receipt[](rawReceipts.length); |
||
| 442 |
for (uint256 i; i < rawReceipts.length; i++) {
|
||
| 443 |
receipts[i] = rawToConvertedReceipt(rawReceipts[i]); |
||
| 444 |
} |
||
| 445 |
return receipts; |
||
| 446 |
} |
||
| 447 | |||
| 448 |
function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
|
||
| 449 |
Receipt memory receipt; |
||
| 450 |
receipt.blockHash = rawReceipt.blockHash; |
||
| 451 |
receipt.to = rawReceipt.to; |
||
| 452 |
receipt.from = rawReceipt.from; |
||
| 453 |
receipt.contractAddress = rawReceipt.contractAddress; |
||
| 454 |
receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice); |
||
| 455 |
receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed); |
||
| 456 |
receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed); |
||
| 457 |
receipt.status = _bytesToUint(rawReceipt.status); |
||
| 458 |
receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex); |
||
| 459 |
receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber); |
||
| 460 |
receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs); |
||
| 461 |
receipt.logsBloom = rawReceipt.logsBloom; |
||
| 462 |
receipt.transactionHash = rawReceipt.transactionHash; |
||
| 463 |
return receipt; |
||
| 464 |
} |
||
| 465 | |||
| 466 |
function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) |
||
| 467 |
internal |
||
| 468 |
pure |
||
| 469 |
virtual |
||
| 470 |
returns (ReceiptLog[] memory) |
||
| 471 |
{
|
||
| 472 |
ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length); |
||
| 473 |
for (uint256 i; i < rawLogs.length; i++) {
|
||
| 474 |
logs[i].logAddress = rawLogs[i].logAddress; |
||
| 475 |
logs[i].blockHash = rawLogs[i].blockHash; |
||
| 476 |
logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber); |
||
| 477 |
logs[i].data = rawLogs[i].data; |
||
| 478 |
logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex); |
||
| 479 |
logs[i].topics = rawLogs[i].topics; |
||
| 480 |
logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex); |
||
| 481 |
logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex); |
||
| 482 |
logs[i].removed = rawLogs[i].removed; |
||
| 483 |
} |
||
| 484 |
return logs; |
||
| 485 |
} |
||
| 486 | |||
| 487 |
// Deploy a contract by fetching the contract bytecode from |
||
| 488 |
// the artifacts directory |
||
| 489 |
// e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` |
||
| 490 |
function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
|
||
| 491 |
bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); |
||
| 492 |
/// @solidity memory-safe-assembly |
||
| 493 |
assembly {
|
||
| 494 |
addr := create(0, add(bytecode, 0x20), mload(bytecode)) |
||
| 495 |
} |
||
| 496 | |||
| 497 |
require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); |
||
| 498 |
} |
||
| 499 | |||
| 500 |
function deployCode(string memory what) internal virtual returns (address addr) {
|
||
| 501 |
bytes memory bytecode = vm.getCode(what); |
||
| 502 |
/// @solidity memory-safe-assembly |
||
| 503 |
assembly {
|
||
| 504 |
addr := create(0, add(bytecode, 0x20), mload(bytecode)) |
||
| 505 |
} |
||
| 506 | |||
| 507 |
require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); |
||
| 508 |
} |
||
| 509 | |||
| 510 |
/// @dev deploy contract with value on construction |
||
| 511 |
function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
|
||
| 512 |
bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); |
||
| 513 |
/// @solidity memory-safe-assembly |
||
| 514 |
assembly {
|
||
| 515 |
addr := create(val, add(bytecode, 0x20), mload(bytecode)) |
||
| 516 |
} |
||
| 517 | |||
| 518 |
require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); |
||
| 519 |
} |
||
| 520 | |||
| 521 |
function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
|
||
| 522 |
bytes memory bytecode = vm.getCode(what); |
||
| 523 |
/// @solidity memory-safe-assembly |
||
| 524 |
assembly {
|
||
| 525 |
addr := create(val, add(bytecode, 0x20), mload(bytecode)) |
||
| 526 |
} |
||
| 527 | |||
| 528 |
require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); |
||
| 529 |
} |
||
| 530 | |||
| 531 |
// creates a labeled address and the corresponding private key |
||
| 532 |
function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
|
||
| 533 |
privateKey = uint256(keccak256(abi.encodePacked(name))); |
||
| 534 |
addr = vm.addr(privateKey); |
||
| 535 |
vm.label(addr, name); |
||
| 536 |
} |
||
| 537 | |||
| 538 |
// creates a labeled address |
||
| 539 |
function makeAddr(string memory name) internal virtual returns (address addr) {
|
||
| 540 |
(addr,) = makeAddrAndKey(name); |
||
| 541 |
} |
||
| 542 | |||
| 543 |
// Destroys an account immediately, sending the balance to beneficiary. |
||
| 544 |
// Destroying means: balance will be zero, code will be empty, and nonce will be 0 |
||
| 545 |
// This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce |
||
| 546 |
// only after tx ends, this will run immediately. |
||
| 547 |
function destroyAccount(address who, address beneficiary) internal virtual {
|
||
| 548 |
uint256 currBalance = who.balance; |
||
| 549 |
vm.etch(who, abi.encode()); |
||
| 550 |
vm.deal(who, 0); |
||
| 551 |
vm.resetNonce(who); |
||
| 552 | |||
| 553 |
uint256 beneficiaryBalance = beneficiary.balance; |
||
| 554 |
vm.deal(beneficiary, currBalance + beneficiaryBalance); |
||
| 555 |
} |
||
| 556 | |||
| 557 |
// creates a struct containing both a labeled address and the corresponding private key |
||
| 558 |
function makeAccount(string memory name) internal virtual returns (Account memory account) {
|
||
| 559 |
(account.addr, account.key) = makeAddrAndKey(name); |
||
| 560 |
} |
||
| 561 | |||
| 562 |
function deriveRememberKey(string memory mnemonic, uint32 index) |
||
| 563 |
internal |
||
| 564 |
virtual |
||
| 565 |
returns (address who, uint256 privateKey) |
||
| 566 |
{
|
||
| 567 |
privateKey = vm.deriveKey(mnemonic, index); |
||
| 568 |
who = vm.rememberKey(privateKey); |
||
| 569 |
} |
||
| 570 | |||
| 571 |
function _bytesToUint(bytes memory b) private pure returns (uint256) {
|
||
| 572 |
require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32."); |
||
| 573 |
return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); |
||
| 574 |
} |
||
| 575 | |||
| 576 |
function isFork() internal view virtual returns (bool status) {
|
||
| 577 |
try vm.activeFork() {
|
||
| 578 |
status = true; |
||
| 579 |
} catch (bytes memory) {}
|
||
| 580 |
} |
||
| 581 | |||
| 582 |
modifier skipWhenForking() {
|
||
| 583 |
if (!isFork()) {
|
||
| 584 |
_; |
||
| 585 |
} |
||
| 586 |
} |
||
| 587 | |||
| 588 |
modifier skipWhenNotForking() {
|
||
| 589 |
if (isFork()) {
|
||
| 590 |
_; |
||
| 591 |
} |
||
| 592 |
} |
||
| 593 | |||
| 594 |
modifier noGasMetering() {
|
||
| 595 |
vm.pauseGasMetering(); |
||
| 596 |
// To prevent turning gas monitoring back on with nested functions that use this modifier, |
||
| 597 |
// we check if gasMetering started in the off position. If it did, we don't want to turn |
||
| 598 |
// it back on until we exit the top level function that used the modifier |
||
| 599 |
// |
||
| 600 |
// i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
|
||
| 601 |
// funcA will have `gasStartedOff` as false, funcB will have it as true, |
||
| 602 |
// so we only turn metering back on at the end of the funcA |
||
| 603 |
bool gasStartedOff = gasMeteringOff; |
||
| 604 |
gasMeteringOff = true; |
||
| 605 | |||
| 606 |
_; |
||
| 607 | |||
| 608 |
// if gas metering was on when this modifier was called, turn it back on at the end |
||
| 609 |
if (!gasStartedOff) {
|
||
| 610 |
gasMeteringOff = false; |
||
| 611 |
vm.resumeGasMetering(); |
||
| 612 |
} |
||
| 613 |
} |
||
| 614 | |||
| 615 |
// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no |
||
| 616 |
// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We |
||
| 617 |
// can't simply access the chain ID in a normal view or pure function because the solc View Pure |
||
| 618 |
// Checker changed `chainid` from pure to view in 0.8.0. |
||
| 619 |
function _viewChainId() private view returns (uint256 chainId) {
|
||
| 620 |
// Assembly required since `block.chainid` was introduced in 0.8.0. |
||
| 621 |
assembly {
|
||
| 622 |
chainId := chainid() |
||
| 623 |
} |
||
| 624 | |||
| 625 |
address(this); // Silence warnings in older Solc versions. |
||
| 626 |
} |
||
| 627 | |||
| 628 |
function _pureChainId() private pure returns (uint256 chainId) {
|
||
| 629 |
function() internal view returns (uint256) fnIn = _viewChainId; |
||
| 630 |
function() internal pure returns (uint256) pureChainId; |
||
| 631 |
assembly {
|
||
| 632 |
pureChainId := fnIn |
||
| 633 |
} |
||
| 634 |
chainId = pureChainId(); |
||
| 635 |
} |
||
| 636 |
} |
||
| 637 | |||
| 638 |
// Wrappers around cheatcodes to avoid footguns |
||
| 639 |
abstract contract StdCheats is StdCheatsSafe {
|
||
| 640 |
using stdStorage for StdStorage; |
||
| 641 | |||
| 642 |
StdStorage private stdstore; |
||
| 643 |
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 644 |
address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; |
||
| 645 | |||
| 646 |
// Skip forward or rewind time by the specified number of seconds |
||
| 647 |
function skip(uint256 time) internal virtual {
|
||
| 648 |
vm.warp(block.timestamp + time); |
||
| 649 |
} |
||
| 650 | |||
| 651 |
function rewind(uint256 time) internal virtual {
|
||
| 652 |
vm.warp(block.timestamp - time); |
||
| 653 |
} |
||
| 654 | |||
| 655 |
// Setup a prank from an address that has some ether |
||
| 656 |
function hoax(address msgSender) internal virtual {
|
||
| 657 |
vm.deal(msgSender, 1 << 128); |
||
| 658 |
vm.prank(msgSender); |
||
| 659 |
} |
||
| 660 | |||
| 661 |
function hoax(address msgSender, uint256 give) internal virtual {
|
||
| 662 |
vm.deal(msgSender, give); |
||
| 663 |
vm.prank(msgSender); |
||
| 664 |
} |
||
| 665 | |||
| 666 |
function hoax(address msgSender, address origin) internal virtual {
|
||
| 667 |
vm.deal(msgSender, 1 << 128); |
||
| 668 |
vm.prank(msgSender, origin); |
||
| 669 |
} |
||
| 670 | |||
| 671 |
function hoax(address msgSender, address origin, uint256 give) internal virtual {
|
||
| 672 |
vm.deal(msgSender, give); |
||
| 673 |
vm.prank(msgSender, origin); |
||
| 674 |
} |
||
| 675 | |||
| 676 |
// Start perpetual prank from an address that has some ether |
||
| 677 |
function startHoax(address msgSender) internal virtual {
|
||
| 678 |
vm.deal(msgSender, 1 << 128); |
||
| 679 |
vm.startPrank(msgSender); |
||
| 680 |
} |
||
| 681 | |||
| 682 |
function startHoax(address msgSender, uint256 give) internal virtual {
|
||
| 683 |
vm.deal(msgSender, give); |
||
| 684 |
vm.startPrank(msgSender); |
||
| 685 |
} |
||
| 686 | |||
| 687 |
// Start perpetual prank from an address that has some ether |
||
| 688 |
// tx.origin is set to the origin parameter |
||
| 689 |
function startHoax(address msgSender, address origin) internal virtual {
|
||
| 690 |
vm.deal(msgSender, 1 << 128); |
||
| 691 |
vm.startPrank(msgSender, origin); |
||
| 692 |
} |
||
| 693 | |||
| 694 |
function startHoax(address msgSender, address origin, uint256 give) internal virtual {
|
||
| 695 |
vm.deal(msgSender, give); |
||
| 696 |
vm.startPrank(msgSender, origin); |
||
| 697 |
} |
||
| 698 | |||
| 699 |
function changePrank(address msgSender) internal virtual {
|
||
| 700 |
console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
|
||
| 701 |
vm.stopPrank(); |
||
| 702 |
vm.startPrank(msgSender); |
||
| 703 |
} |
||
| 704 | |||
| 705 |
function changePrank(address msgSender, address txOrigin) internal virtual {
|
||
| 706 |
vm.stopPrank(); |
||
| 707 |
vm.startPrank(msgSender, txOrigin); |
||
| 708 |
} |
||
| 709 | |||
| 710 |
// The same as Vm's `deal` |
||
| 711 |
// Use the alternative signature for ERC20 tokens |
||
| 712 |
function deal(address to, uint256 give) internal virtual {
|
||
| 713 |
vm.deal(to, give); |
||
| 714 |
} |
||
| 715 | |||
| 716 |
// Set the balance of an account for any ERC20 token |
||
| 717 |
// Use the alternative signature to update `totalSupply` |
||
| 718 |
function deal(address token, address to, uint256 give) internal virtual {
|
||
| 719 |
deal(token, to, give, false); |
||
| 720 |
} |
||
| 721 | |||
| 722 |
// Set the balance of an account for any ERC1155 token |
||
| 723 |
// Use the alternative signature to update `totalSupply` |
||
| 724 |
function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
|
||
| 725 |
dealERC1155(token, to, id, give, false); |
||
| 726 |
} |
||
| 727 | |||
| 728 |
function deal(address token, address to, uint256 give, bool adjust) internal virtual {
|
||
| 729 |
// get current balance |
||
| 730 |
(, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); |
||
| 731 |
uint256 prevBal = abi.decode(balData, (uint256)); |
||
| 732 | |||
| 733 |
// update balance |
||
| 734 |
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); |
||
| 735 | |||
| 736 |
// update total supply |
||
| 737 |
if (adjust) {
|
||
| 738 |
(, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd)); |
||
| 739 |
uint256 totSup = abi.decode(totSupData, (uint256)); |
||
| 740 |
if (give < prevBal) {
|
||
| 741 |
totSup -= (prevBal - give); |
||
| 742 |
} else {
|
||
| 743 |
totSup += (give - prevBal); |
||
| 744 |
} |
||
| 745 |
stdstore.target(token).sig(0x18160ddd).checked_write(totSup); |
||
| 746 |
} |
||
| 747 |
} |
||
| 748 | |||
| 749 |
function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
|
||
| 750 |
// get current balance |
||
| 751 |
(, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); |
||
| 752 |
uint256 prevBal = abi.decode(balData, (uint256)); |
||
| 753 | |||
| 754 |
// update balance |
||
| 755 |
stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); |
||
| 756 | |||
| 757 |
// update total supply |
||
| 758 |
if (adjust) {
|
||
| 759 |
(, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); |
||
| 760 |
require( |
||
| 761 |
totSupData.length != 0, |
||
| 762 |
"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." |
||
| 763 |
); |
||
| 764 |
uint256 totSup = abi.decode(totSupData, (uint256)); |
||
| 765 |
if (give < prevBal) {
|
||
| 766 |
totSup -= (prevBal - give); |
||
| 767 |
} else {
|
||
| 768 |
totSup += (give - prevBal); |
||
| 769 |
} |
||
| 770 |
stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); |
||
| 771 |
} |
||
| 772 |
} |
||
| 773 | |||
| 774 |
function dealERC721(address token, address to, uint256 id) internal virtual {
|
||
| 775 |
// check if token id is already minted and the actual owner. |
||
| 776 |
(bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); |
||
| 777 |
require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); |
||
| 778 | |||
| 779 |
// get owner current balance |
||
| 780 |
(, bytes memory fromBalData) = |
||
| 781 |
token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address)))); |
||
| 782 |
uint256 fromPrevBal = abi.decode(fromBalData, (uint256)); |
||
| 783 | |||
| 784 |
// get new user current balance |
||
| 785 |
(, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); |
||
| 786 |
uint256 toPrevBal = abi.decode(toBalData, (uint256)); |
||
| 787 | |||
| 788 |
// update balances |
||
| 789 |
stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); |
||
| 790 |
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); |
||
| 791 | |||
| 792 |
// update owner |
||
| 793 |
stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); |
||
| 794 |
} |
||
| 795 | |||
| 796 |
function deployCodeTo(string memory what, address where) internal virtual {
|
||
| 797 |
deployCodeTo(what, "", 0, where); |
||
| 798 |
} |
||
| 799 | |||
| 800 |
function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
|
||
| 801 |
deployCodeTo(what, args, 0, where); |
||
| 802 |
} |
||
| 803 | |||
| 804 |
function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
|
||
| 805 |
bytes memory creationCode = vm.getCode(what); |
||
| 806 |
vm.etch(where, abi.encodePacked(creationCode, args)); |
||
| 807 |
(bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
|
||
| 808 |
require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode."); |
||
| 809 |
vm.etch(where, runtimeBytecode); |
||
| 810 |
} |
||
| 811 | |||
| 812 |
// Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. |
||
| 813 |
function console2_log_StdCheats(string memory p0) private view {
|
||
| 814 |
(bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
|
||
| 815 |
status; |
||
| 816 |
} |
||
| 817 |
} |
||
| 818 |
| Lines covered: | 0 / 10 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test |
||
| 3 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 4 | |||
| 5 |
library stdError {
|
||
| 6 |
bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
|
||
| 7 |
bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);
|
||
| 8 |
bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12);
|
||
| 9 |
bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21);
|
||
| 10 |
bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22);
|
||
| 11 |
bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31);
|
||
| 12 |
bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32);
|
||
| 13 |
bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41);
|
||
| 14 |
bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51);
|
||
| 15 |
} |
||
| 16 |
| Lines covered: | 0 / 20 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
abstract contract StdInvariant {
|
||
| 7 |
struct FuzzSelector {
|
||
| 8 |
address addr; |
||
| 9 |
bytes4[] selectors; |
||
| 10 |
} |
||
| 11 | |||
| 12 |
struct FuzzArtifactSelector {
|
||
| 13 |
string artifact; |
||
| 14 |
bytes4[] selectors; |
||
| 15 |
} |
||
| 16 | |||
| 17 |
struct FuzzInterface {
|
||
| 18 |
address addr; |
||
| 19 |
string[] artifacts; |
||
| 20 |
} |
||
| 21 | |||
| 22 |
address[] private _excludedContracts; |
||
| 23 |
address[] private _excludedSenders; |
||
| 24 |
address[] private _targetedContracts; |
||
| 25 |
address[] private _targetedSenders; |
||
| 26 | |||
| 27 |
string[] private _excludedArtifacts; |
||
| 28 |
string[] private _targetedArtifacts; |
||
| 29 | |||
| 30 |
FuzzArtifactSelector[] private _targetedArtifactSelectors; |
||
| 31 | |||
| 32 |
FuzzSelector[] private _excludedSelectors; |
||
| 33 |
FuzzSelector[] private _targetedSelectors; |
||
| 34 | |||
| 35 |
FuzzInterface[] private _targetedInterfaces; |
||
| 36 | |||
| 37 |
// Functions for users: |
||
| 38 |
// These are intended to be called in tests. |
||
| 39 | |||
| 40 |
function excludeContract(address newExcludedContract_) internal {
|
||
| 41 |
_excludedContracts.push(newExcludedContract_); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function excludeSelector(FuzzSelector memory newExcludedSelector_) internal {
|
||
| 45 |
_excludedSelectors.push(newExcludedSelector_); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function excludeSender(address newExcludedSender_) internal {
|
||
| 49 |
_excludedSenders.push(newExcludedSender_); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function excludeArtifact(string memory newExcludedArtifact_) internal {
|
||
| 53 |
_excludedArtifacts.push(newExcludedArtifact_); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function targetArtifact(string memory newTargetedArtifact_) internal {
|
||
| 57 |
_targetedArtifacts.push(newTargetedArtifact_); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal {
|
||
| 61 |
_targetedArtifactSelectors.push(newTargetedArtifactSelector_); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function targetContract(address newTargetedContract_) internal {
|
||
| 65 |
_targetedContracts.push(newTargetedContract_); |
||
| 66 |
} |
||
| 67 | |||
| 68 |
function targetSelector(FuzzSelector memory newTargetedSelector_) internal {
|
||
| 69 |
_targetedSelectors.push(newTargetedSelector_); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function targetSender(address newTargetedSender_) internal {
|
||
| 73 |
_targetedSenders.push(newTargetedSender_); |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function targetInterface(FuzzInterface memory newTargetedInterface_) internal {
|
||
| 77 |
_targetedInterfaces.push(newTargetedInterface_); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
// Functions for forge: |
||
| 81 |
// These are called by forge to run invariant tests and don't need to be called in tests. |
||
| 82 | |||
| 83 |
function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {
|
||
| 84 |
excludedArtifacts_ = _excludedArtifacts; |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function excludeContracts() public view returns (address[] memory excludedContracts_) {
|
||
| 88 |
excludedContracts_ = _excludedContracts; |
||
| 89 |
} |
||
| 90 | |||
| 91 |
function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) {
|
||
| 92 |
excludedSelectors_ = _excludedSelectors; |
||
| 93 |
} |
||
| 94 | |||
| 95 |
function excludeSenders() public view returns (address[] memory excludedSenders_) {
|
||
| 96 |
excludedSenders_ = _excludedSenders; |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {
|
||
| 100 |
targetedArtifacts_ = _targetedArtifacts; |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) {
|
||
| 104 |
targetedArtifactSelectors_ = _targetedArtifactSelectors; |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function targetContracts() public view returns (address[] memory targetedContracts_) {
|
||
| 108 |
targetedContracts_ = _targetedContracts; |
||
| 109 |
} |
||
| 110 | |||
| 111 |
function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {
|
||
| 112 |
targetedSelectors_ = _targetedSelectors; |
||
| 113 |
} |
||
| 114 | |||
| 115 |
function targetSenders() public view returns (address[] memory targetedSenders_) {
|
||
| 116 |
targetedSenders_ = _targetedSenders; |
||
| 117 |
} |
||
| 118 | |||
| 119 |
function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) {
|
||
| 120 |
targetedInterfaces_ = _targetedInterfaces; |
||
| 121 |
} |
||
| 122 |
} |
||
| 123 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.0 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
import {VmSafe} from "./Vm.sol";
|
||
| 7 | |||
| 8 |
// Helpers for parsing and writing JSON files |
||
| 9 |
// To parse: |
||
| 10 |
// ``` |
||
| 11 |
// using stdJson for string; |
||
| 12 |
// string memory json = vm.readFile("<some_path>");
|
||
| 13 |
// json.readUint("<json_path>");
|
||
| 14 |
// ``` |
||
| 15 |
// To write: |
||
| 16 |
// ``` |
||
| 17 |
// using stdJson for string; |
||
| 18 |
// string memory json = "json"; |
||
| 19 |
// json.serialize("a", uint256(123));
|
||
| 20 |
// string memory semiFinal = json.serialize("b", string("test"));
|
||
| 21 |
// string memory finalJson = json.serialize("c", semiFinal);
|
||
| 22 |
// finalJson.write("<some_path>");
|
||
| 23 |
// ``` |
||
| 24 | |||
| 25 |
library stdJson {
|
||
| 26 |
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 27 | |||
| 28 |
function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
|
||
| 29 |
return vm.parseJson(json, key); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function readUint(string memory json, string memory key) internal pure returns (uint256) {
|
||
| 33 |
return vm.parseJsonUint(json, key); |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
|
||
| 37 |
return vm.parseJsonUintArray(json, key); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function readInt(string memory json, string memory key) internal pure returns (int256) {
|
||
| 41 |
return vm.parseJsonInt(json, key); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
|
||
| 45 |
return vm.parseJsonIntArray(json, key); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
|
||
| 49 |
return vm.parseJsonBytes32(json, key); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
|
||
| 53 |
return vm.parseJsonBytes32Array(json, key); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function readString(string memory json, string memory key) internal pure returns (string memory) {
|
||
| 57 |
return vm.parseJsonString(json, key); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
|
||
| 61 |
return vm.parseJsonStringArray(json, key); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function readAddress(string memory json, string memory key) internal pure returns (address) {
|
||
| 65 |
return vm.parseJsonAddress(json, key); |
||
| 66 |
} |
||
| 67 | |||
| 68 |
function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
|
||
| 69 |
return vm.parseJsonAddressArray(json, key); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function readBool(string memory json, string memory key) internal pure returns (bool) {
|
||
| 73 |
return vm.parseJsonBool(json, key); |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
|
||
| 77 |
return vm.parseJsonBoolArray(json, key); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
|
||
| 81 |
return vm.parseJsonBytes(json, key); |
||
| 82 |
} |
||
| 83 | |||
| 84 |
function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
|
||
| 85 |
return vm.parseJsonBytesArray(json, key); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
|
||
| 89 |
return vm.serializeJson(jsonKey, rootObject); |
||
| 90 |
} |
||
| 91 | |||
| 92 |
function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
|
||
| 93 |
return vm.serializeBool(jsonKey, key, value); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
function serialize(string memory jsonKey, string memory key, bool[] memory value) |
||
| 97 |
internal |
||
| 98 |
returns (string memory) |
||
| 99 |
{
|
||
| 100 |
return vm.serializeBool(jsonKey, key, value); |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
|
||
| 104 |
return vm.serializeUint(jsonKey, key, value); |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function serialize(string memory jsonKey, string memory key, uint256[] memory value) |
||
| 108 |
internal |
||
| 109 |
returns (string memory) |
||
| 110 |
{
|
||
| 111 |
return vm.serializeUint(jsonKey, key, value); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
|
||
| 115 |
return vm.serializeInt(jsonKey, key, value); |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function serialize(string memory jsonKey, string memory key, int256[] memory value) |
||
| 119 |
internal |
||
| 120 |
returns (string memory) |
||
| 121 |
{
|
||
| 122 |
return vm.serializeInt(jsonKey, key, value); |
||
| 123 |
} |
||
| 124 | |||
| 125 |
function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
|
||
| 126 |
return vm.serializeAddress(jsonKey, key, value); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
function serialize(string memory jsonKey, string memory key, address[] memory value) |
||
| 130 |
internal |
||
| 131 |
returns (string memory) |
||
| 132 |
{
|
||
| 133 |
return vm.serializeAddress(jsonKey, key, value); |
||
| 134 |
} |
||
| 135 | |||
| 136 |
function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
|
||
| 137 |
return vm.serializeBytes32(jsonKey, key, value); |
||
| 138 |
} |
||
| 139 | |||
| 140 |
function serialize(string memory jsonKey, string memory key, bytes32[] memory value) |
||
| 141 |
internal |
||
| 142 |
returns (string memory) |
||
| 143 |
{
|
||
| 144 |
return vm.serializeBytes32(jsonKey, key, value); |
||
| 145 |
} |
||
| 146 | |||
| 147 |
function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
|
||
| 148 |
return vm.serializeBytes(jsonKey, key, value); |
||
| 149 |
} |
||
| 150 | |||
| 151 |
function serialize(string memory jsonKey, string memory key, bytes[] memory value) |
||
| 152 |
internal |
||
| 153 |
returns (string memory) |
||
| 154 |
{
|
||
| 155 |
return vm.serializeBytes(jsonKey, key, value); |
||
| 156 |
} |
||
| 157 | |||
| 158 |
function serialize(string memory jsonKey, string memory key, string memory value) |
||
| 159 |
internal |
||
| 160 |
returns (string memory) |
||
| 161 |
{
|
||
| 162 |
return vm.serializeString(jsonKey, key, value); |
||
| 163 |
} |
||
| 164 | |||
| 165 |
function serialize(string memory jsonKey, string memory key, string[] memory value) |
||
| 166 |
internal |
||
| 167 |
returns (string memory) |
||
| 168 |
{
|
||
| 169 |
return vm.serializeString(jsonKey, key, value); |
||
| 170 |
} |
||
| 171 | |||
| 172 |
function write(string memory jsonKey, string memory path) internal {
|
||
| 173 |
vm.writeJson(jsonKey, path); |
||
| 174 |
} |
||
| 175 | |||
| 176 |
function write(string memory jsonKey, string memory path, string memory valueKey) internal {
|
||
| 177 |
vm.writeJson(jsonKey, path, valueKey); |
||
| 178 |
} |
||
| 179 |
} |
||
| 180 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
library stdMath {
|
||
| 5 |
int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; |
||
| 6 | |||
| 7 |
function abs(int256 a) internal pure returns (uint256) {
|
||
| 8 |
// Required or it will fail when `a = type(int256).min` |
||
| 9 |
if (a == INT256_MIN) {
|
||
| 10 |
return 57896044618658097711785492504343953926634992332820282019728792003956564819968; |
||
| 11 |
} |
||
| 12 | |||
| 13 |
return uint256(a > 0 ? a : -a); |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function delta(uint256 a, uint256 b) internal pure returns (uint256) {
|
||
| 17 |
return a > b ? a - b : b - a; |
||
| 18 |
} |
||
| 19 | |||
| 20 |
function delta(int256 a, int256 b) internal pure returns (uint256) {
|
||
| 21 |
// a and b are of the same sign |
||
| 22 |
// this works thanks to two's complement, the left-most bit is the sign bit |
||
| 23 |
if ((a ^ b) > -1) {
|
||
| 24 |
return delta(abs(a), abs(b)); |
||
| 25 |
} |
||
| 26 | |||
| 27 |
// a and b are of opposite signs |
||
| 28 |
return abs(a) + abs(b); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
|
||
| 32 |
uint256 absDelta = delta(a, b); |
||
| 33 | |||
| 34 |
return absDelta * 1e18 / b; |
||
| 35 |
} |
||
| 36 | |||
| 37 |
function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
|
||
| 38 |
uint256 absDelta = delta(a, b); |
||
| 39 |
uint256 absB = abs(b); |
||
| 40 | |||
| 41 |
return absDelta * 1e18 / absB; |
||
| 42 |
} |
||
| 43 |
} |
||
| 44 |
| Lines covered: | 0 / 2 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
import {Vm} from "./Vm.sol";
|
||
| 5 | |||
| 6 |
struct FindData {
|
||
| 7 |
uint256 slot; |
||
| 8 |
uint256 offsetLeft; |
||
| 9 |
uint256 offsetRight; |
||
| 10 |
bool found; |
||
| 11 |
} |
||
| 12 | |||
| 13 |
struct StdStorage {
|
||
| 14 |
mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds; |
||
| 15 |
bytes32[] _keys; |
||
| 16 |
bytes4 _sig; |
||
| 17 |
uint256 _depth; |
||
| 18 |
address _target; |
||
| 19 |
bytes32 _set; |
||
| 20 |
bool _enable_packed_slots; |
||
| 21 |
bytes _calldata; |
||
| 22 |
} |
||
| 23 | |||
| 24 |
library stdStorageSafe {
|
||
| 25 |
event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot); |
||
| 26 |
event WARNING_UninitedSlot(address who, uint256 slot); |
||
| 27 | |||
| 28 |
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 29 |
uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; |
||
| 30 | |||
| 31 |
function sigs(string memory sigStr) internal pure returns (bytes4) {
|
||
| 32 |
return bytes4(keccak256(bytes(sigStr))); |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function getCallParams(StdStorage storage self) internal view returns (bytes memory) {
|
||
| 36 |
if (self._calldata.length == 0) {
|
||
| 37 |
return flatten(self._keys); |
||
| 38 |
} else {
|
||
| 39 |
return self._calldata; |
||
| 40 |
} |
||
| 41 |
} |
||
| 42 | |||
| 43 |
// Calls target contract with configured parameters |
||
| 44 |
function callTarget(StdStorage storage self) internal view returns (bool, bytes32) {
|
||
| 45 |
bytes memory cald = abi.encodePacked(self._sig, getCallParams(self)); |
||
| 46 |
(bool success, bytes memory rdat) = self._target.staticcall(cald); |
||
| 47 |
bytes32 result = bytesToBytes32(rdat, 32 * self._depth); |
||
| 48 | |||
| 49 |
return (success, result); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
// Tries mutating slot value to determine if the targeted value is stored in it. |
||
| 53 |
// If current value is 0, then we are setting slot value to type(uint256).max |
||
| 54 |
// Otherwise, we set it to 0. That way, return value should always be affected. |
||
| 55 |
function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) {
|
||
| 56 |
bytes32 prevSlotValue = vm.load(self._target, slot); |
||
| 57 |
(bool success, bytes32 prevReturnValue) = callTarget(self); |
||
| 58 | |||
| 59 |
bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0); |
||
| 60 |
vm.store(self._target, slot, testVal); |
||
| 61 | |||
| 62 |
(, bytes32 newReturnValue) = callTarget(self); |
||
| 63 | |||
| 64 |
vm.store(self._target, slot, prevSlotValue); |
||
| 65 | |||
| 66 |
return (success && (prevReturnValue != newReturnValue)); |
||
| 67 |
} |
||
| 68 | |||
| 69 |
// Tries setting one of the bits in slot to 1 until return value changes. |
||
| 70 |
// Index of resulted bit is an offset packed slot has from left/right side |
||
| 71 |
function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) {
|
||
| 72 |
for (uint256 offset = 0; offset < 256; offset++) {
|
||
| 73 |
uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); |
||
| 74 |
vm.store(self._target, slot, bytes32(valueToPut)); |
||
| 75 | |||
| 76 |
(bool success, bytes32 data) = callTarget(self); |
||
| 77 | |||
| 78 |
if (success && (uint256(data) > 0)) {
|
||
| 79 |
return (true, offset); |
||
| 80 |
} |
||
| 81 |
} |
||
| 82 |
return (false, 0); |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) {
|
||
| 86 |
bytes32 prevSlotValue = vm.load(self._target, slot); |
||
| 87 | |||
| 88 |
(bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true); |
||
| 89 |
(bool foundRight, uint256 offsetRight) = findOffset(self, slot, false); |
||
| 90 | |||
| 91 |
// `findOffset` may mutate slot value, so we are setting it to initial value |
||
| 92 |
vm.store(self._target, slot, prevSlotValue); |
||
| 93 |
return (foundLeft && foundRight, offsetLeft, offsetRight); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
function find(StdStorage storage self) internal returns (FindData storage) {
|
||
| 97 |
return find(self, true); |
||
| 98 |
} |
||
| 99 | |||
| 100 |
/// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against |
||
| 101 |
// slot complexity: |
||
| 102 |
// if flat, will be bytes32(uint256(uint)); |
||
| 103 |
// if map, will be keccak256(abi.encode(key, uint(slot))); |
||
| 104 |
// if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))); |
||
| 105 |
// if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth); |
||
| 106 |
function find(StdStorage storage self, bool _clear) internal returns (FindData storage) {
|
||
| 107 |
address who = self._target; |
||
| 108 |
bytes4 fsig = self._sig; |
||
| 109 |
uint256 field_depth = self._depth; |
||
| 110 |
bytes memory params = getCallParams(self); |
||
| 111 | |||
| 112 |
// calldata to test against |
||
| 113 |
if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
|
||
| 114 |
if (_clear) {
|
||
| 115 |
clear(self); |
||
| 116 |
} |
||
| 117 |
return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; |
||
| 118 |
} |
||
| 119 |
vm.record(); |
||
| 120 |
(, bytes32 callResult) = callTarget(self); |
||
| 121 |
(bytes32[] memory reads,) = vm.accesses(address(who)); |
||
| 122 | |||
| 123 |
if (reads.length == 0) {
|
||
| 124 |
revert("stdStorage find(StdStorage): No storage use detected for target.");
|
||
| 125 |
} else {
|
||
| 126 |
for (uint256 i = reads.length; --i >= 0;) {
|
||
| 127 |
bytes32 prev = vm.load(who, reads[i]); |
||
| 128 |
if (prev == bytes32(0)) {
|
||
| 129 |
emit WARNING_UninitedSlot(who, uint256(reads[i])); |
||
| 130 |
} |
||
| 131 | |||
| 132 |
if (!checkSlotMutatesCall(self, reads[i])) {
|
||
| 133 |
continue; |
||
| 134 |
} |
||
| 135 | |||
| 136 |
(uint256 offsetLeft, uint256 offsetRight) = (0, 0); |
||
| 137 | |||
| 138 |
if (self._enable_packed_slots) {
|
||
| 139 |
bool found; |
||
| 140 |
(found, offsetLeft, offsetRight) = findOffsets(self, reads[i]); |
||
| 141 |
if (!found) {
|
||
| 142 |
continue; |
||
| 143 |
} |
||
| 144 |
} |
||
| 145 | |||
| 146 |
// Check that value between found offsets is equal to the current call result |
||
| 147 |
uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight; |
||
| 148 | |||
| 149 |
if (uint256(callResult) != curVal) {
|
||
| 150 |
continue; |
||
| 151 |
} |
||
| 152 | |||
| 153 |
emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i])); |
||
| 154 |
self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] = |
||
| 155 |
FindData(uint256(reads[i]), offsetLeft, offsetRight, true); |
||
| 156 |
break; |
||
| 157 |
} |
||
| 158 |
} |
||
| 159 | |||
| 160 |
require( |
||
| 161 |
self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found, |
||
| 162 |
"stdStorage find(StdStorage): Slot(s) not found." |
||
| 163 |
); |
||
| 164 | |||
| 165 |
if (_clear) {
|
||
| 166 |
clear(self); |
||
| 167 |
} |
||
| 168 |
return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
|
||
| 172 |
self._target = _target; |
||
| 173 |
return self; |
||
| 174 |
} |
||
| 175 | |||
| 176 |
function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
|
||
| 177 |
self._sig = _sig; |
||
| 178 |
return self; |
||
| 179 |
} |
||
| 180 | |||
| 181 |
function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
|
||
| 182 |
self._sig = sigs(_sig); |
||
| 183 |
return self; |
||
| 184 |
} |
||
| 185 | |||
| 186 |
function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
|
||
| 187 |
self._calldata = _calldata; |
||
| 188 |
return self; |
||
| 189 |
} |
||
| 190 | |||
| 191 |
function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
|
||
| 192 |
self._keys.push(bytes32(uint256(uint160(who)))); |
||
| 193 |
return self; |
||
| 194 |
} |
||
| 195 | |||
| 196 |
function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
|
||
| 197 |
self._keys.push(bytes32(amt)); |
||
| 198 |
return self; |
||
| 199 |
} |
||
| 200 | |||
| 201 |
function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
|
||
| 202 |
self._keys.push(key); |
||
| 203 |
return self; |
||
| 204 |
} |
||
| 205 | |||
| 206 |
function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
|
||
| 207 |
self._enable_packed_slots = true; |
||
| 208 |
return self; |
||
| 209 |
} |
||
| 210 | |||
| 211 |
function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
|
||
| 212 |
self._depth = _depth; |
||
| 213 |
return self; |
||
| 214 |
} |
||
| 215 | |||
| 216 |
function read(StdStorage storage self) private returns (bytes memory) {
|
||
| 217 |
FindData storage data = find(self, false); |
||
| 218 |
uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); |
||
| 219 |
uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; |
||
| 220 |
clear(self); |
||
| 221 |
return abi.encode(value); |
||
| 222 |
} |
||
| 223 | |||
| 224 |
function read_bytes32(StdStorage storage self) internal returns (bytes32) {
|
||
| 225 |
return abi.decode(read(self), (bytes32)); |
||
| 226 |
} |
||
| 227 | |||
| 228 |
function read_bool(StdStorage storage self) internal returns (bool) {
|
||
| 229 |
int256 v = read_int(self); |
||
| 230 |
if (v == 0) return false; |
||
| 231 |
if (v == 1) return true; |
||
| 232 |
revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
|
||
| 233 |
} |
||
| 234 | |||
| 235 |
function read_address(StdStorage storage self) internal returns (address) {
|
||
| 236 |
return abi.decode(read(self), (address)); |
||
| 237 |
} |
||
| 238 | |||
| 239 |
function read_uint(StdStorage storage self) internal returns (uint256) {
|
||
| 240 |
return abi.decode(read(self), (uint256)); |
||
| 241 |
} |
||
| 242 | |||
| 243 |
function read_int(StdStorage storage self) internal returns (int256) {
|
||
| 244 |
return abi.decode(read(self), (int256)); |
||
| 245 |
} |
||
| 246 | |||
| 247 |
function parent(StdStorage storage self) internal returns (uint256, bytes32) {
|
||
| 248 |
address who = self._target; |
||
| 249 |
uint256 field_depth = self._depth; |
||
| 250 |
vm.startMappingRecording(); |
||
| 251 |
uint256 child = find(self, true).slot - field_depth; |
||
| 252 |
(bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); |
||
| 253 |
if (!found) {
|
||
| 254 |
revert( |
||
| 255 |
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." |
||
| 256 |
); |
||
| 257 |
} |
||
| 258 |
return (uint256(parent_slot), key); |
||
| 259 |
} |
||
| 260 | |||
| 261 |
function root(StdStorage storage self) internal returns (uint256) {
|
||
| 262 |
address who = self._target; |
||
| 263 |
uint256 field_depth = self._depth; |
||
| 264 |
vm.startMappingRecording(); |
||
| 265 |
uint256 child = find(self, true).slot - field_depth; |
||
| 266 |
bool found; |
||
| 267 |
bytes32 root_slot; |
||
| 268 |
bytes32 parent_slot; |
||
| 269 |
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); |
||
| 270 |
if (!found) {
|
||
| 271 |
revert( |
||
| 272 |
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." |
||
| 273 |
); |
||
| 274 |
} |
||
| 275 |
while (found) {
|
||
| 276 |
root_slot = parent_slot; |
||
| 277 |
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot)); |
||
| 278 |
} |
||
| 279 |
return uint256(root_slot); |
||
| 280 |
} |
||
| 281 | |||
| 282 |
function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
|
||
| 283 |
bytes32 out; |
||
| 284 | |||
| 285 |
uint256 max = b.length > 32 ? 32 : b.length; |
||
| 286 |
for (uint256 i = 0; i < max; i++) {
|
||
| 287 |
out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); |
||
| 288 |
} |
||
| 289 |
return out; |
||
| 290 |
} |
||
| 291 | |||
| 292 |
function flatten(bytes32[] memory b) private pure returns (bytes memory) {
|
||
| 293 |
bytes memory result = new bytes(b.length * 32); |
||
| 294 |
for (uint256 i = 0; i < b.length; i++) {
|
||
| 295 |
bytes32 k = b[i]; |
||
| 296 |
/// @solidity memory-safe-assembly |
||
| 297 |
assembly {
|
||
| 298 |
mstore(add(result, add(32, mul(32, i))), k) |
||
| 299 |
} |
||
| 300 |
} |
||
| 301 | |||
| 302 |
return result; |
||
| 303 |
} |
||
| 304 | |||
| 305 |
function clear(StdStorage storage self) internal {
|
||
| 306 |
delete self._target; |
||
| 307 |
delete self._sig; |
||
| 308 |
delete self._keys; |
||
| 309 |
delete self._depth; |
||
| 310 |
delete self._enable_packed_slots; |
||
| 311 |
delete self._calldata; |
||
| 312 |
} |
||
| 313 | |||
| 314 |
// Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` |
||
| 315 |
// (slotValue & mask) >> offsetRight will be the value of the given packed variable |
||
| 316 |
function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) {
|
||
| 317 |
// mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; |
||
| 318 |
// using assembly because (1 << 256) causes overflow |
||
| 319 |
assembly {
|
||
| 320 |
mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1)) |
||
| 321 |
} |
||
| 322 |
} |
||
| 323 | |||
| 324 |
// Returns slot value with updated packed variable. |
||
| 325 |
function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) |
||
| 326 |
internal |
||
| 327 |
pure |
||
| 328 |
returns (bytes32 newValue) |
||
| 329 |
{
|
||
| 330 |
return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight)); |
||
| 331 |
} |
||
| 332 |
} |
||
| 333 | |||
| 334 |
library stdStorage {
|
||
| 335 |
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 336 | |||
| 337 |
function sigs(string memory sigStr) internal pure returns (bytes4) {
|
||
| 338 |
return stdStorageSafe.sigs(sigStr); |
||
| 339 |
} |
||
| 340 | |||
| 341 |
function find(StdStorage storage self) internal returns (uint256) {
|
||
| 342 |
return find(self, true); |
||
| 343 |
} |
||
| 344 | |||
| 345 |
function find(StdStorage storage self, bool _clear) internal returns (uint256) {
|
||
| 346 |
return stdStorageSafe.find(self, _clear).slot; |
||
| 347 |
} |
||
| 348 | |||
| 349 |
function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
|
||
| 350 |
return stdStorageSafe.target(self, _target); |
||
| 351 |
} |
||
| 352 | |||
| 353 |
function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
|
||
| 354 |
return stdStorageSafe.sig(self, _sig); |
||
| 355 |
} |
||
| 356 | |||
| 357 |
function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
|
||
| 358 |
return stdStorageSafe.sig(self, _sig); |
||
| 359 |
} |
||
| 360 | |||
| 361 |
function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
|
||
| 362 |
return stdStorageSafe.with_key(self, who); |
||
| 363 |
} |
||
| 364 | |||
| 365 |
function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
|
||
| 366 |
return stdStorageSafe.with_key(self, amt); |
||
| 367 |
} |
||
| 368 | |||
| 369 |
function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
|
||
| 370 |
return stdStorageSafe.with_key(self, key); |
||
| 371 |
} |
||
| 372 | |||
| 373 |
function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
|
||
| 374 |
return stdStorageSafe.with_calldata(self, _calldata); |
||
| 375 |
} |
||
| 376 | |||
| 377 |
function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
|
||
| 378 |
return stdStorageSafe.enable_packed_slots(self); |
||
| 379 |
} |
||
| 380 | |||
| 381 |
function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
|
||
| 382 |
return stdStorageSafe.depth(self, _depth); |
||
| 383 |
} |
||
| 384 | |||
| 385 |
function clear(StdStorage storage self) internal {
|
||
| 386 |
stdStorageSafe.clear(self); |
||
| 387 |
} |
||
| 388 | |||
| 389 |
function checked_write(StdStorage storage self, address who) internal {
|
||
| 390 |
checked_write(self, bytes32(uint256(uint160(who)))); |
||
| 391 |
} |
||
| 392 | |||
| 393 |
function checked_write(StdStorage storage self, uint256 amt) internal {
|
||
| 394 |
checked_write(self, bytes32(amt)); |
||
| 395 |
} |
||
| 396 | |||
| 397 |
function checked_write_int(StdStorage storage self, int256 val) internal {
|
||
| 398 |
checked_write(self, bytes32(uint256(val))); |
||
| 399 |
} |
||
| 400 | |||
| 401 |
function checked_write(StdStorage storage self, bool write) internal {
|
||
| 402 |
bytes32 t; |
||
| 403 |
/// @solidity memory-safe-assembly |
||
| 404 |
assembly {
|
||
| 405 |
t := write |
||
| 406 |
} |
||
| 407 |
checked_write(self, t); |
||
| 408 |
} |
||
| 409 | |||
| 410 |
function checked_write(StdStorage storage self, bytes32 set) internal {
|
||
| 411 |
address who = self._target; |
||
| 412 |
bytes4 fsig = self._sig; |
||
| 413 |
uint256 field_depth = self._depth; |
||
| 414 |
bytes memory params = stdStorageSafe.getCallParams(self); |
||
| 415 | |||
| 416 |
if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
|
||
| 417 |
find(self, false); |
||
| 418 |
} |
||
| 419 |
FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; |
||
| 420 |
if ((data.offsetLeft + data.offsetRight) > 0) {
|
||
| 421 |
uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight)); |
||
| 422 |
require( |
||
| 423 |
uint256(set) < maxVal, |
||
| 424 |
string( |
||
| 425 |
abi.encodePacked( |
||
| 426 |
"stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", |
||
| 427 |
vm.toString(maxVal) |
||
| 428 |
) |
||
| 429 |
) |
||
| 430 |
); |
||
| 431 |
} |
||
| 432 |
bytes32 curVal = vm.load(who, bytes32(data.slot)); |
||
| 433 |
bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight); |
||
| 434 | |||
| 435 |
vm.store(who, bytes32(data.slot), valToSet); |
||
| 436 | |||
| 437 |
(bool success, bytes32 callResult) = stdStorageSafe.callTarget(self); |
||
| 438 | |||
| 439 |
if (!success || callResult != set) {
|
||
| 440 |
vm.store(who, bytes32(data.slot), curVal); |
||
| 441 |
revert("stdStorage find(StdStorage): Failed to write value.");
|
||
| 442 |
} |
||
| 443 |
clear(self); |
||
| 444 |
} |
||
| 445 | |||
| 446 |
function read_bytes32(StdStorage storage self) internal returns (bytes32) {
|
||
| 447 |
return stdStorageSafe.read_bytes32(self); |
||
| 448 |
} |
||
| 449 | |||
| 450 |
function read_bool(StdStorage storage self) internal returns (bool) {
|
||
| 451 |
return stdStorageSafe.read_bool(self); |
||
| 452 |
} |
||
| 453 | |||
| 454 |
function read_address(StdStorage storage self) internal returns (address) {
|
||
| 455 |
return stdStorageSafe.read_address(self); |
||
| 456 |
} |
||
| 457 | |||
| 458 |
function read_uint(StdStorage storage self) internal returns (uint256) {
|
||
| 459 |
return stdStorageSafe.read_uint(self); |
||
| 460 |
} |
||
| 461 | |||
| 462 |
function read_int(StdStorage storage self) internal returns (int256) {
|
||
| 463 |
return stdStorageSafe.read_int(self); |
||
| 464 |
} |
||
| 465 | |||
| 466 |
function parent(StdStorage storage self) internal returns (uint256, bytes32) {
|
||
| 467 |
return stdStorageSafe.parent(self); |
||
| 468 |
} |
||
| 469 | |||
| 470 |
function root(StdStorage storage self) internal returns (uint256) {
|
||
| 471 |
return stdStorageSafe.root(self); |
||
| 472 |
} |
||
| 473 |
} |
||
| 474 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.4.22 <0.9.0; |
||
| 3 | |||
| 4 |
import {VmSafe} from "./Vm.sol";
|
||
| 5 | |||
| 6 |
library StdStyle {
|
||
| 7 |
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 8 | |||
| 9 |
string constant RED = "\u001b[91m"; |
||
| 10 |
string constant GREEN = "\u001b[92m"; |
||
| 11 |
string constant YELLOW = "\u001b[93m"; |
||
| 12 |
string constant BLUE = "\u001b[94m"; |
||
| 13 |
string constant MAGENTA = "\u001b[95m"; |
||
| 14 |
string constant CYAN = "\u001b[96m"; |
||
| 15 |
string constant BOLD = "\u001b[1m"; |
||
| 16 |
string constant DIM = "\u001b[2m"; |
||
| 17 |
string constant ITALIC = "\u001b[3m"; |
||
| 18 |
string constant UNDERLINE = "\u001b[4m"; |
||
| 19 |
string constant INVERSE = "\u001b[7m"; |
||
| 20 |
string constant RESET = "\u001b[0m"; |
||
| 21 | |||
| 22 |
function styleConcat(string memory style, string memory self) private pure returns (string memory) {
|
||
| 23 |
return string(abi.encodePacked(style, self, RESET)); |
||
| 24 |
} |
||
| 25 | |||
| 26 |
function red(string memory self) internal pure returns (string memory) {
|
||
| 27 |
return styleConcat(RED, self); |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function red(uint256 self) internal pure returns (string memory) {
|
||
| 31 |
return red(vm.toString(self)); |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function red(int256 self) internal pure returns (string memory) {
|
||
| 35 |
return red(vm.toString(self)); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function red(address self) internal pure returns (string memory) {
|
||
| 39 |
return red(vm.toString(self)); |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function red(bool self) internal pure returns (string memory) {
|
||
| 43 |
return red(vm.toString(self)); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function redBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 47 |
return red(vm.toString(self)); |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function redBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 51 |
return red(vm.toString(self)); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
function green(string memory self) internal pure returns (string memory) {
|
||
| 55 |
return styleConcat(GREEN, self); |
||
| 56 |
} |
||
| 57 | |||
| 58 |
function green(uint256 self) internal pure returns (string memory) {
|
||
| 59 |
return green(vm.toString(self)); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function green(int256 self) internal pure returns (string memory) {
|
||
| 63 |
return green(vm.toString(self)); |
||
| 64 |
} |
||
| 65 | |||
| 66 |
function green(address self) internal pure returns (string memory) {
|
||
| 67 |
return green(vm.toString(self)); |
||
| 68 |
} |
||
| 69 | |||
| 70 |
function green(bool self) internal pure returns (string memory) {
|
||
| 71 |
return green(vm.toString(self)); |
||
| 72 |
} |
||
| 73 | |||
| 74 |
function greenBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 75 |
return green(vm.toString(self)); |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function greenBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 79 |
return green(vm.toString(self)); |
||
| 80 |
} |
||
| 81 | |||
| 82 |
function yellow(string memory self) internal pure returns (string memory) {
|
||
| 83 |
return styleConcat(YELLOW, self); |
||
| 84 |
} |
||
| 85 | |||
| 86 |
function yellow(uint256 self) internal pure returns (string memory) {
|
||
| 87 |
return yellow(vm.toString(self)); |
||
| 88 |
} |
||
| 89 | |||
| 90 |
function yellow(int256 self) internal pure returns (string memory) {
|
||
| 91 |
return yellow(vm.toString(self)); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function yellow(address self) internal pure returns (string memory) {
|
||
| 95 |
return yellow(vm.toString(self)); |
||
| 96 |
} |
||
| 97 | |||
| 98 |
function yellow(bool self) internal pure returns (string memory) {
|
||
| 99 |
return yellow(vm.toString(self)); |
||
| 100 |
} |
||
| 101 | |||
| 102 |
function yellowBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 103 |
return yellow(vm.toString(self)); |
||
| 104 |
} |
||
| 105 | |||
| 106 |
function yellowBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 107 |
return yellow(vm.toString(self)); |
||
| 108 |
} |
||
| 109 | |||
| 110 |
function blue(string memory self) internal pure returns (string memory) {
|
||
| 111 |
return styleConcat(BLUE, self); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function blue(uint256 self) internal pure returns (string memory) {
|
||
| 115 |
return blue(vm.toString(self)); |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function blue(int256 self) internal pure returns (string memory) {
|
||
| 119 |
return blue(vm.toString(self)); |
||
| 120 |
} |
||
| 121 | |||
| 122 |
function blue(address self) internal pure returns (string memory) {
|
||
| 123 |
return blue(vm.toString(self)); |
||
| 124 |
} |
||
| 125 | |||
| 126 |
function blue(bool self) internal pure returns (string memory) {
|
||
| 127 |
return blue(vm.toString(self)); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
function blueBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 131 |
return blue(vm.toString(self)); |
||
| 132 |
} |
||
| 133 | |||
| 134 |
function blueBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 135 |
return blue(vm.toString(self)); |
||
| 136 |
} |
||
| 137 | |||
| 138 |
function magenta(string memory self) internal pure returns (string memory) {
|
||
| 139 |
return styleConcat(MAGENTA, self); |
||
| 140 |
} |
||
| 141 | |||
| 142 |
function magenta(uint256 self) internal pure returns (string memory) {
|
||
| 143 |
return magenta(vm.toString(self)); |
||
| 144 |
} |
||
| 145 | |||
| 146 |
function magenta(int256 self) internal pure returns (string memory) {
|
||
| 147 |
return magenta(vm.toString(self)); |
||
| 148 |
} |
||
| 149 | |||
| 150 |
function magenta(address self) internal pure returns (string memory) {
|
||
| 151 |
return magenta(vm.toString(self)); |
||
| 152 |
} |
||
| 153 | |||
| 154 |
function magenta(bool self) internal pure returns (string memory) {
|
||
| 155 |
return magenta(vm.toString(self)); |
||
| 156 |
} |
||
| 157 | |||
| 158 |
function magentaBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 159 |
return magenta(vm.toString(self)); |
||
| 160 |
} |
||
| 161 | |||
| 162 |
function magentaBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 163 |
return magenta(vm.toString(self)); |
||
| 164 |
} |
||
| 165 | |||
| 166 |
function cyan(string memory self) internal pure returns (string memory) {
|
||
| 167 |
return styleConcat(CYAN, self); |
||
| 168 |
} |
||
| 169 | |||
| 170 |
function cyan(uint256 self) internal pure returns (string memory) {
|
||
| 171 |
return cyan(vm.toString(self)); |
||
| 172 |
} |
||
| 173 | |||
| 174 |
function cyan(int256 self) internal pure returns (string memory) {
|
||
| 175 |
return cyan(vm.toString(self)); |
||
| 176 |
} |
||
| 177 | |||
| 178 |
function cyan(address self) internal pure returns (string memory) {
|
||
| 179 |
return cyan(vm.toString(self)); |
||
| 180 |
} |
||
| 181 | |||
| 182 |
function cyan(bool self) internal pure returns (string memory) {
|
||
| 183 |
return cyan(vm.toString(self)); |
||
| 184 |
} |
||
| 185 | |||
| 186 |
function cyanBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 187 |
return cyan(vm.toString(self)); |
||
| 188 |
} |
||
| 189 | |||
| 190 |
function cyanBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 191 |
return cyan(vm.toString(self)); |
||
| 192 |
} |
||
| 193 | |||
| 194 |
function bold(string memory self) internal pure returns (string memory) {
|
||
| 195 |
return styleConcat(BOLD, self); |
||
| 196 |
} |
||
| 197 | |||
| 198 |
function bold(uint256 self) internal pure returns (string memory) {
|
||
| 199 |
return bold(vm.toString(self)); |
||
| 200 |
} |
||
| 201 | |||
| 202 |
function bold(int256 self) internal pure returns (string memory) {
|
||
| 203 |
return bold(vm.toString(self)); |
||
| 204 |
} |
||
| 205 | |||
| 206 |
function bold(address self) internal pure returns (string memory) {
|
||
| 207 |
return bold(vm.toString(self)); |
||
| 208 |
} |
||
| 209 | |||
| 210 |
function bold(bool self) internal pure returns (string memory) {
|
||
| 211 |
return bold(vm.toString(self)); |
||
| 212 |
} |
||
| 213 | |||
| 214 |
function boldBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 215 |
return bold(vm.toString(self)); |
||
| 216 |
} |
||
| 217 | |||
| 218 |
function boldBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 219 |
return bold(vm.toString(self)); |
||
| 220 |
} |
||
| 221 | |||
| 222 |
function dim(string memory self) internal pure returns (string memory) {
|
||
| 223 |
return styleConcat(DIM, self); |
||
| 224 |
} |
||
| 225 | |||
| 226 |
function dim(uint256 self) internal pure returns (string memory) {
|
||
| 227 |
return dim(vm.toString(self)); |
||
| 228 |
} |
||
| 229 | |||
| 230 |
function dim(int256 self) internal pure returns (string memory) {
|
||
| 231 |
return dim(vm.toString(self)); |
||
| 232 |
} |
||
| 233 | |||
| 234 |
function dim(address self) internal pure returns (string memory) {
|
||
| 235 |
return dim(vm.toString(self)); |
||
| 236 |
} |
||
| 237 | |||
| 238 |
function dim(bool self) internal pure returns (string memory) {
|
||
| 239 |
return dim(vm.toString(self)); |
||
| 240 |
} |
||
| 241 | |||
| 242 |
function dimBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 243 |
return dim(vm.toString(self)); |
||
| 244 |
} |
||
| 245 | |||
| 246 |
function dimBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 247 |
return dim(vm.toString(self)); |
||
| 248 |
} |
||
| 249 | |||
| 250 |
function italic(string memory self) internal pure returns (string memory) {
|
||
| 251 |
return styleConcat(ITALIC, self); |
||
| 252 |
} |
||
| 253 | |||
| 254 |
function italic(uint256 self) internal pure returns (string memory) {
|
||
| 255 |
return italic(vm.toString(self)); |
||
| 256 |
} |
||
| 257 | |||
| 258 |
function italic(int256 self) internal pure returns (string memory) {
|
||
| 259 |
return italic(vm.toString(self)); |
||
| 260 |
} |
||
| 261 | |||
| 262 |
function italic(address self) internal pure returns (string memory) {
|
||
| 263 |
return italic(vm.toString(self)); |
||
| 264 |
} |
||
| 265 | |||
| 266 |
function italic(bool self) internal pure returns (string memory) {
|
||
| 267 |
return italic(vm.toString(self)); |
||
| 268 |
} |
||
| 269 | |||
| 270 |
function italicBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 271 |
return italic(vm.toString(self)); |
||
| 272 |
} |
||
| 273 | |||
| 274 |
function italicBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 275 |
return italic(vm.toString(self)); |
||
| 276 |
} |
||
| 277 | |||
| 278 |
function underline(string memory self) internal pure returns (string memory) {
|
||
| 279 |
return styleConcat(UNDERLINE, self); |
||
| 280 |
} |
||
| 281 | |||
| 282 |
function underline(uint256 self) internal pure returns (string memory) {
|
||
| 283 |
return underline(vm.toString(self)); |
||
| 284 |
} |
||
| 285 | |||
| 286 |
function underline(int256 self) internal pure returns (string memory) {
|
||
| 287 |
return underline(vm.toString(self)); |
||
| 288 |
} |
||
| 289 | |||
| 290 |
function underline(address self) internal pure returns (string memory) {
|
||
| 291 |
return underline(vm.toString(self)); |
||
| 292 |
} |
||
| 293 | |||
| 294 |
function underline(bool self) internal pure returns (string memory) {
|
||
| 295 |
return underline(vm.toString(self)); |
||
| 296 |
} |
||
| 297 | |||
| 298 |
function underlineBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 299 |
return underline(vm.toString(self)); |
||
| 300 |
} |
||
| 301 | |||
| 302 |
function underlineBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 303 |
return underline(vm.toString(self)); |
||
| 304 |
} |
||
| 305 | |||
| 306 |
function inverse(string memory self) internal pure returns (string memory) {
|
||
| 307 |
return styleConcat(INVERSE, self); |
||
| 308 |
} |
||
| 309 | |||
| 310 |
function inverse(uint256 self) internal pure returns (string memory) {
|
||
| 311 |
return inverse(vm.toString(self)); |
||
| 312 |
} |
||
| 313 | |||
| 314 |
function inverse(int256 self) internal pure returns (string memory) {
|
||
| 315 |
return inverse(vm.toString(self)); |
||
| 316 |
} |
||
| 317 | |||
| 318 |
function inverse(address self) internal pure returns (string memory) {
|
||
| 319 |
return inverse(vm.toString(self)); |
||
| 320 |
} |
||
| 321 | |||
| 322 |
function inverse(bool self) internal pure returns (string memory) {
|
||
| 323 |
return inverse(vm.toString(self)); |
||
| 324 |
} |
||
| 325 | |||
| 326 |
function inverseBytes(bytes memory self) internal pure returns (string memory) {
|
||
| 327 |
return inverse(vm.toString(self)); |
||
| 328 |
} |
||
| 329 | |||
| 330 |
function inverseBytes32(bytes32 self) internal pure returns (string memory) {
|
||
| 331 |
return inverse(vm.toString(self)); |
||
| 332 |
} |
||
| 333 |
} |
||
| 334 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.0 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
import {VmSafe} from "./Vm.sol";
|
||
| 7 | |||
| 8 |
// Helpers for parsing and writing TOML files |
||
| 9 |
// To parse: |
||
| 10 |
// ``` |
||
| 11 |
// using stdToml for string; |
||
| 12 |
// string memory toml = vm.readFile("<some_path>");
|
||
| 13 |
// toml.readUint("<json_path>");
|
||
| 14 |
// ``` |
||
| 15 |
// To write: |
||
| 16 |
// ``` |
||
| 17 |
// using stdToml for string; |
||
| 18 |
// string memory json = "json"; |
||
| 19 |
// json.serialize("a", uint256(123));
|
||
| 20 |
// string memory semiFinal = json.serialize("b", string("test"));
|
||
| 21 |
// string memory finalJson = json.serialize("c", semiFinal);
|
||
| 22 |
// finalJson.write("<some_path>");
|
||
| 23 |
// ``` |
||
| 24 | |||
| 25 |
library stdToml {
|
||
| 26 |
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 27 | |||
| 28 |
function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) {
|
||
| 29 |
return vm.parseToml(toml, key); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function readUint(string memory toml, string memory key) internal pure returns (uint256) {
|
||
| 33 |
return vm.parseTomlUint(toml, key); |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) {
|
||
| 37 |
return vm.parseTomlUintArray(toml, key); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function readInt(string memory toml, string memory key) internal pure returns (int256) {
|
||
| 41 |
return vm.parseTomlInt(toml, key); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) {
|
||
| 45 |
return vm.parseTomlIntArray(toml, key); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) {
|
||
| 49 |
return vm.parseTomlBytes32(toml, key); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) {
|
||
| 53 |
return vm.parseTomlBytes32Array(toml, key); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function readString(string memory toml, string memory key) internal pure returns (string memory) {
|
||
| 57 |
return vm.parseTomlString(toml, key); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) {
|
||
| 61 |
return vm.parseTomlStringArray(toml, key); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function readAddress(string memory toml, string memory key) internal pure returns (address) {
|
||
| 65 |
return vm.parseTomlAddress(toml, key); |
||
| 66 |
} |
||
| 67 | |||
| 68 |
function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) {
|
||
| 69 |
return vm.parseTomlAddressArray(toml, key); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function readBool(string memory toml, string memory key) internal pure returns (bool) {
|
||
| 73 |
return vm.parseTomlBool(toml, key); |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) {
|
||
| 77 |
return vm.parseTomlBoolArray(toml, key); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) {
|
||
| 81 |
return vm.parseTomlBytes(toml, key); |
||
| 82 |
} |
||
| 83 | |||
| 84 |
function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) {
|
||
| 85 |
return vm.parseTomlBytesArray(toml, key); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
|
||
| 89 |
return vm.serializeJson(jsonKey, rootObject); |
||
| 90 |
} |
||
| 91 | |||
| 92 |
function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
|
||
| 93 |
return vm.serializeBool(jsonKey, key, value); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
function serialize(string memory jsonKey, string memory key, bool[] memory value) |
||
| 97 |
internal |
||
| 98 |
returns (string memory) |
||
| 99 |
{
|
||
| 100 |
return vm.serializeBool(jsonKey, key, value); |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
|
||
| 104 |
return vm.serializeUint(jsonKey, key, value); |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function serialize(string memory jsonKey, string memory key, uint256[] memory value) |
||
| 108 |
internal |
||
| 109 |
returns (string memory) |
||
| 110 |
{
|
||
| 111 |
return vm.serializeUint(jsonKey, key, value); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
|
||
| 115 |
return vm.serializeInt(jsonKey, key, value); |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function serialize(string memory jsonKey, string memory key, int256[] memory value) |
||
| 119 |
internal |
||
| 120 |
returns (string memory) |
||
| 121 |
{
|
||
| 122 |
return vm.serializeInt(jsonKey, key, value); |
||
| 123 |
} |
||
| 124 | |||
| 125 |
function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
|
||
| 126 |
return vm.serializeAddress(jsonKey, key, value); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
function serialize(string memory jsonKey, string memory key, address[] memory value) |
||
| 130 |
internal |
||
| 131 |
returns (string memory) |
||
| 132 |
{
|
||
| 133 |
return vm.serializeAddress(jsonKey, key, value); |
||
| 134 |
} |
||
| 135 | |||
| 136 |
function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
|
||
| 137 |
return vm.serializeBytes32(jsonKey, key, value); |
||
| 138 |
} |
||
| 139 | |||
| 140 |
function serialize(string memory jsonKey, string memory key, bytes32[] memory value) |
||
| 141 |
internal |
||
| 142 |
returns (string memory) |
||
| 143 |
{
|
||
| 144 |
return vm.serializeBytes32(jsonKey, key, value); |
||
| 145 |
} |
||
| 146 | |||
| 147 |
function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
|
||
| 148 |
return vm.serializeBytes(jsonKey, key, value); |
||
| 149 |
} |
||
| 150 | |||
| 151 |
function serialize(string memory jsonKey, string memory key, bytes[] memory value) |
||
| 152 |
internal |
||
| 153 |
returns (string memory) |
||
| 154 |
{
|
||
| 155 |
return vm.serializeBytes(jsonKey, key, value); |
||
| 156 |
} |
||
| 157 | |||
| 158 |
function serialize(string memory jsonKey, string memory key, string memory value) |
||
| 159 |
internal |
||
| 160 |
returns (string memory) |
||
| 161 |
{
|
||
| 162 |
return vm.serializeString(jsonKey, key, value); |
||
| 163 |
} |
||
| 164 | |||
| 165 |
function serialize(string memory jsonKey, string memory key, string[] memory value) |
||
| 166 |
internal |
||
| 167 |
returns (string memory) |
||
| 168 |
{
|
||
| 169 |
return vm.serializeString(jsonKey, key, value); |
||
| 170 |
} |
||
| 171 | |||
| 172 |
function write(string memory jsonKey, string memory path) internal {
|
||
| 173 |
vm.writeToml(jsonKey, path); |
||
| 174 |
} |
||
| 175 | |||
| 176 |
function write(string memory jsonKey, string memory path, string memory valueKey) internal {
|
||
| 177 |
vm.writeToml(jsonKey, path, valueKey); |
||
| 178 |
} |
||
| 179 |
} |
||
| 180 |
| Lines covered: | 0 / 38 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
import {IMulticall3} from "./interfaces/IMulticall3.sol";
|
||
| 7 |
import {MockERC20} from "./mocks/MockERC20.sol";
|
||
| 8 |
import {MockERC721} from "./mocks/MockERC721.sol";
|
||
| 9 |
import {VmSafe} from "./Vm.sol";
|
||
| 10 | |||
| 11 |
abstract contract StdUtils {
|
||
| 12 |
/*////////////////////////////////////////////////////////////////////////// |
||
| 13 |
CONSTANTS |
||
| 14 |
//////////////////////////////////////////////////////////////////////////*/ |
||
| 15 | |||
| 16 |
IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); |
||
| 17 |
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 18 |
address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; |
||
| 19 |
uint256 private constant INT256_MIN_ABS = |
||
| 20 |
57896044618658097711785492504343953926634992332820282019728792003956564819968; |
||
| 21 |
uint256 private constant SECP256K1_ORDER = |
||
| 22 |
115792089237316195423570985008687907852837564279074904382605163141518161494337; |
||
| 23 |
uint256 private constant UINT256_MAX = |
||
| 24 |
115792089237316195423570985008687907853269984665640564039457584007913129639935; |
||
| 25 | |||
| 26 |
// Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. |
||
| 27 |
address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; |
||
| 28 | |||
| 29 |
/*////////////////////////////////////////////////////////////////////////// |
||
| 30 |
INTERNAL FUNCTIONS |
||
| 31 |
//////////////////////////////////////////////////////////////////////////*/ |
||
| 32 | |||
| 33 |
function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
|
||
| 34 |
require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); |
||
| 35 |
// If x is between min and max, return x directly. This is to ensure that dictionary values |
||
| 36 |
// do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 |
||
| 37 |
if (x >= min && x <= max) return x; |
||
| 38 | |||
| 39 |
uint256 size = max - min + 1; |
||
| 40 | |||
| 41 |
// If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. |
||
| 42 |
// This helps ensure coverage of the min/max values. |
||
| 43 |
if (x <= 3 && size > x) return min + x; |
||
| 44 |
if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); |
||
| 45 | |||
| 46 |
// Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. |
||
| 47 |
if (x > max) {
|
||
| 48 |
uint256 diff = x - max; |
||
| 49 |
uint256 rem = diff % size; |
||
| 50 |
if (rem == 0) return max; |
||
| 51 |
result = min + rem - 1; |
||
| 52 |
} else if (x < min) {
|
||
| 53 |
uint256 diff = min - x; |
||
| 54 |
uint256 rem = diff % size; |
||
| 55 |
if (rem == 0) return min; |
||
| 56 |
result = max - rem + 1; |
||
| 57 |
} |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
|
||
| 61 |
result = _bound(x, min, max); |
||
| 62 |
console2_log_StdUtils("Bound result", result);
|
||
| 63 |
} |
||
| 64 | |||
| 65 |
function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
|
||
| 66 |
require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); |
||
| 67 | |||
| 68 |
// Shifting all int256 values to uint256 to use _bound function. The range of two types are: |
||
| 69 |
// int256 : -(2**255) ~ (2**255 - 1) |
||
| 70 |
// uint256: 0 ~ (2**256 - 1) |
||
| 71 |
// So, add 2**255, INT256_MIN_ABS to the integer values. |
||
| 72 |
// |
||
| 73 |
// If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. |
||
| 74 |
// So, use `~uint256(x) + 1` instead. |
||
| 75 |
uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); |
||
| 76 |
uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); |
||
| 77 |
uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); |
||
| 78 | |||
| 79 |
uint256 y = _bound(_x, _min, _max); |
||
| 80 | |||
| 81 |
// To move it back to int256 value, subtract INT256_MIN_ABS at here. |
||
| 82 |
result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
|
||
| 86 |
result = _bound(x, min, max); |
||
| 87 |
console2_log_StdUtils("Bound result", vm.toString(result));
|
||
| 88 |
} |
||
| 89 | |||
| 90 |
function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
|
||
| 91 |
result = _bound(privateKey, 1, SECP256K1_ORDER - 1); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
|
||
| 95 |
require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); |
||
| 96 |
return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
/// @dev Compute the address a contract will be deployed at for a given deployer address and nonce |
||
| 100 |
/// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) |
||
| 101 |
function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
|
||
| 102 |
console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
|
||
| 103 |
return vm.computeCreateAddress(deployer, nonce); |
||
| 104 |
} |
||
| 105 | |||
| 106 |
function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) |
||
| 107 |
internal |
||
| 108 |
pure |
||
| 109 |
virtual |
||
| 110 |
returns (address) |
||
| 111 |
{
|
||
| 112 |
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
|
||
| 113 |
return vm.computeCreate2Address(salt, initcodeHash, deployer); |
||
| 114 |
} |
||
| 115 | |||
| 116 |
/// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer |
||
| 117 |
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
|
||
| 118 |
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
|
||
| 119 |
return vm.computeCreate2Address(salt, initCodeHash); |
||
| 120 |
} |
||
| 121 | |||
| 122 |
/// @dev returns an initialized mock ERC20 contract |
||
| 123 |
function deployMockERC20(string memory name, string memory symbol, uint8 decimals) |
||
| 124 |
internal |
||
| 125 |
returns (MockERC20 mock) |
||
| 126 |
{
|
||
| 127 |
mock = new MockERC20(); |
||
| 128 |
mock.initialize(name, symbol, decimals); |
||
| 129 |
} |
||
| 130 | |||
| 131 |
/// @dev returns an initialized mock ERC721 contract |
||
| 132 |
function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) {
|
||
| 133 |
mock = new MockERC721(); |
||
| 134 |
mock.initialize(name, symbol); |
||
| 135 |
} |
||
| 136 | |||
| 137 |
/// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments |
||
| 138 |
/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode |
||
| 139 |
function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
|
||
| 140 |
return hashInitCode(creationCode, ""); |
||
| 141 |
} |
||
| 142 | |||
| 143 |
/// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 |
||
| 144 |
/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode |
||
| 145 |
/// @param args the ABI-encoded arguments to the constructor of C |
||
| 146 |
function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
|
||
| 147 |
return keccak256(abi.encodePacked(creationCode, args)); |
||
| 148 |
} |
||
| 149 | |||
| 150 |
// Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. |
||
| 151 |
function getTokenBalances(address token, address[] memory addresses) |
||
| 152 |
internal |
||
| 153 |
virtual |
||
| 154 |
returns (uint256[] memory balances) |
||
| 155 |
{
|
||
| 156 |
uint256 tokenCodeSize; |
||
| 157 |
assembly {
|
||
| 158 |
tokenCodeSize := extcodesize(token) |
||
| 159 |
} |
||
| 160 |
require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); |
||
| 161 | |||
| 162 |
// ABI encode the aggregate call to Multicall3. |
||
| 163 |
uint256 length = addresses.length; |
||
| 164 |
IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); |
||
| 165 |
for (uint256 i = 0; i < length; ++i) {
|
||
| 166 |
// 0x70a08231 = bytes4("balanceOf(address)"))
|
||
| 167 |
calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
|
||
| 168 |
} |
||
| 169 | |||
| 170 |
// Make the aggregate call. |
||
| 171 |
(, bytes[] memory returnData) = multicall.aggregate(calls); |
||
| 172 | |||
| 173 |
// ABI decode the return data and return the balances. |
||
| 174 |
balances = new uint256[](length); |
||
| 175 |
for (uint256 i = 0; i < length; ++i) {
|
||
| 176 |
balances[i] = abi.decode(returnData[i], (uint256)); |
||
| 177 |
} |
||
| 178 |
} |
||
| 179 | |||
| 180 |
/*////////////////////////////////////////////////////////////////////////// |
||
| 181 |
PRIVATE FUNCTIONS |
||
| 182 |
//////////////////////////////////////////////////////////////////////////*/ |
||
| 183 | |||
| 184 |
function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
|
||
| 185 |
return address(uint160(uint256(bytesValue))); |
||
| 186 |
} |
||
| 187 | |||
| 188 |
// This section is used to prevent the compilation of console, which shortens the compilation time when console is |
||
| 189 |
// not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid |
||
| 190 |
// any breaking changes to function signatures. |
||
| 191 |
function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) |
||
| 192 |
internal |
||
| 193 |
pure |
||
| 194 |
returns (function(bytes memory) internal pure fnOut) |
||
| 195 |
{
|
||
| 196 |
assembly {
|
||
| 197 |
fnOut := fnIn |
||
| 198 |
} |
||
| 199 |
} |
||
| 200 | |||
| 201 |
function _sendLogPayload(bytes memory payload) internal pure {
|
||
| 202 |
_castLogPayloadViewToPure(_sendLogPayloadView)(payload); |
||
| 203 |
} |
||
| 204 | |||
| 205 |
function _sendLogPayloadView(bytes memory payload) private view {
|
||
| 206 |
uint256 payloadLength = payload.length; |
||
| 207 |
address consoleAddress = CONSOLE2_ADDRESS; |
||
| 208 |
/// @solidity memory-safe-assembly |
||
| 209 |
assembly {
|
||
| 210 |
let payloadStart := add(payload, 32) |
||
| 211 |
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) |
||
| 212 |
} |
||
| 213 |
} |
||
| 214 | |||
| 215 |
function console2_log_StdUtils(string memory p0) private pure {
|
||
| 216 |
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
|
||
| 217 |
} |
||
| 218 | |||
| 219 |
function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
|
||
| 220 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
|
||
| 221 |
} |
||
| 222 | |||
| 223 |
function console2_log_StdUtils(string memory p0, string memory p1) private pure {
|
||
| 224 |
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
|
||
| 225 |
} |
||
| 226 |
} |
||
| 227 |
| Lines covered: | 1 / 1 (100.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
// 💬 ABOUT |
||
| 7 |
// Forge Std's default Test. |
||
| 8 | |||
| 9 |
// 🧩 MODULES |
||
| 10 |
import {console} from "./console.sol";
|
||
| 11 |
import {console2} from "./console2.sol";
|
||
| 12 |
import {safeconsole} from "./safeconsole.sol";
|
||
| 13 |
import {StdAssertions} from "./StdAssertions.sol";
|
||
| 14 |
import {StdChains} from "./StdChains.sol";
|
||
| 15 |
import {StdCheats} from "./StdCheats.sol";
|
||
| 16 |
import {stdError} from "./StdError.sol";
|
||
| 17 |
import {StdInvariant} from "./StdInvariant.sol";
|
||
| 18 |
import {stdJson} from "./StdJson.sol";
|
||
| 19 |
import {stdMath} from "./StdMath.sol";
|
||
| 20 |
import {StdStorage, stdStorage} from "./StdStorage.sol";
|
||
| 21 |
import {StdStyle} from "./StdStyle.sol";
|
||
| 22 |
import {stdToml} from "./StdToml.sol";
|
||
| 23 |
import {StdUtils} from "./StdUtils.sol";
|
||
| 24 |
import {Vm} from "./Vm.sol";
|
||
| 25 | |||
| 26 |
// 📦 BOILERPLATE |
||
| 27 |
import {TestBase} from "./Base.sol";
|
||
| 28 | |||
| 29 |
// ⭐️ TEST |
||
| 30 |
abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils {
|
||
| 31 |
// Note: IS_TEST() must return true. |
||
| 32 |
√ 31
|
bool public IS_TEST = true; |
|
| 33 |
} |
||
| 34 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// Automatically @generated by scripts/vm.py. Do not modify manually. |
||
| 2 | |||
| 3 |
// SPDX-License-Identifier: MIT OR Apache-2.0 |
||
| 4 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 5 |
pragma experimental ABIEncoderV2; |
||
| 6 | |||
| 7 |
/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may |
||
| 8 |
/// result in Script simulations differing from on-chain execution. It is recommended to only use |
||
| 9 |
/// these cheats in scripts. |
||
| 10 |
interface VmSafe {
|
||
| 11 |
/// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`. |
||
| 12 |
enum CallerMode {
|
||
| 13 |
// No caller modification is currently active. |
||
| 14 |
None, |
||
| 15 |
// A one time broadcast triggered by a `vm.broadcast()` call is currently active. |
||
| 16 |
Broadcast, |
||
| 17 |
// A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active. |
||
| 18 |
RecurrentBroadcast, |
||
| 19 |
// A one time prank triggered by a `vm.prank()` call is currently active. |
||
| 20 |
Prank, |
||
| 21 |
// A recurrent prank triggered by a `vm.startPrank()` call is currently active. |
||
| 22 |
RecurrentPrank |
||
| 23 |
} |
||
| 24 | |||
| 25 |
/// The kind of account access that occurred. |
||
| 26 |
enum AccountAccessKind {
|
||
| 27 |
// The account was called. |
||
| 28 |
Call, |
||
| 29 |
// The account was called via delegatecall. |
||
| 30 |
DelegateCall, |
||
| 31 |
// The account was called via callcode. |
||
| 32 |
CallCode, |
||
| 33 |
// The account was called via staticcall. |
||
| 34 |
StaticCall, |
||
| 35 |
// The account was created. |
||
| 36 |
Create, |
||
| 37 |
// The account was selfdestructed. |
||
| 38 |
SelfDestruct, |
||
| 39 |
// Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess). |
||
| 40 |
Resume, |
||
| 41 |
// The account's balance was read. |
||
| 42 |
Balance, |
||
| 43 |
// The account's codesize was read. |
||
| 44 |
Extcodesize, |
||
| 45 |
// The account's codehash was read. |
||
| 46 |
Extcodehash, |
||
| 47 |
// The account's code was copied. |
||
| 48 |
Extcodecopy |
||
| 49 |
} |
||
| 50 | |||
| 51 |
/// Forge execution contexts. |
||
| 52 |
enum ForgeContext {
|
||
| 53 |
// Test group execution context (test, coverage or snapshot). |
||
| 54 |
TestGroup, |
||
| 55 |
// `forge test` execution context. |
||
| 56 |
Test, |
||
| 57 |
// `forge coverage` execution context. |
||
| 58 |
Coverage, |
||
| 59 |
// `forge snapshot` execution context. |
||
| 60 |
Snapshot, |
||
| 61 |
// Script group execution context (dry run, broadcast or resume). |
||
| 62 |
ScriptGroup, |
||
| 63 |
// `forge script` execution context. |
||
| 64 |
ScriptDryRun, |
||
| 65 |
// `forge script --broadcast` execution context. |
||
| 66 |
ScriptBroadcast, |
||
| 67 |
// `forge script --resume` execution context. |
||
| 68 |
ScriptResume, |
||
| 69 |
// Unknown `forge` execution context. |
||
| 70 |
Unknown |
||
| 71 |
} |
||
| 72 | |||
| 73 |
/// An Ethereum log. Returned by `getRecordedLogs`. |
||
| 74 |
struct Log {
|
||
| 75 |
// The topics of the log, including the signature, if any. |
||
| 76 |
bytes32[] topics; |
||
| 77 |
// The raw data of the log. |
||
| 78 |
bytes data; |
||
| 79 |
// The address of the log's emitter. |
||
| 80 |
address emitter; |
||
| 81 |
} |
||
| 82 | |||
| 83 |
/// An RPC URL and its alias. Returned by `rpcUrlStructs`. |
||
| 84 |
struct Rpc {
|
||
| 85 |
// The alias of the RPC URL. |
||
| 86 |
string key; |
||
| 87 |
// The RPC URL. |
||
| 88 |
string url; |
||
| 89 |
} |
||
| 90 | |||
| 91 |
/// An RPC log object. Returned by `eth_getLogs`. |
||
| 92 |
struct EthGetLogs {
|
||
| 93 |
// The address of the log's emitter. |
||
| 94 |
address emitter; |
||
| 95 |
// The topics of the log, including the signature, if any. |
||
| 96 |
bytes32[] topics; |
||
| 97 |
// The raw data of the log. |
||
| 98 |
bytes data; |
||
| 99 |
// The block hash. |
||
| 100 |
bytes32 blockHash; |
||
| 101 |
// The block number. |
||
| 102 |
uint64 blockNumber; |
||
| 103 |
// The transaction hash. |
||
| 104 |
bytes32 transactionHash; |
||
| 105 |
// The transaction index in the block. |
||
| 106 |
uint64 transactionIndex; |
||
| 107 |
// The log index. |
||
| 108 |
uint256 logIndex; |
||
| 109 |
// Whether the log was removed. |
||
| 110 |
bool removed; |
||
| 111 |
} |
||
| 112 | |||
| 113 |
/// A single entry in a directory listing. Returned by `readDir`. |
||
| 114 |
struct DirEntry {
|
||
| 115 |
// The error message, if any. |
||
| 116 |
string errorMessage; |
||
| 117 |
// The path of the entry. |
||
| 118 |
string path; |
||
| 119 |
// The depth of the entry. |
||
| 120 |
uint64 depth; |
||
| 121 |
// Whether the entry is a directory. |
||
| 122 |
bool isDir; |
||
| 123 |
// Whether the entry is a symlink. |
||
| 124 |
bool isSymlink; |
||
| 125 |
} |
||
| 126 | |||
| 127 |
/// Metadata information about a file. |
||
| 128 |
/// This structure is returned from the `fsMetadata` function and represents known |
||
| 129 |
/// metadata about a file such as its permissions, size, modification |
||
| 130 |
/// times, etc. |
||
| 131 |
struct FsMetadata {
|
||
| 132 |
// True if this metadata is for a directory. |
||
| 133 |
bool isDir; |
||
| 134 |
// True if this metadata is for a symlink. |
||
| 135 |
bool isSymlink; |
||
| 136 |
// The size of the file, in bytes, this metadata is for. |
||
| 137 |
uint256 length; |
||
| 138 |
// True if this metadata is for a readonly (unwritable) file. |
||
| 139 |
bool readOnly; |
||
| 140 |
// The last modification time listed in this metadata. |
||
| 141 |
uint256 modified; |
||
| 142 |
// The last access time of this metadata. |
||
| 143 |
uint256 accessed; |
||
| 144 |
// The creation time listed in this metadata. |
||
| 145 |
uint256 created; |
||
| 146 |
} |
||
| 147 | |||
| 148 |
/// A wallet with a public and private key. |
||
| 149 |
struct Wallet {
|
||
| 150 |
// The wallet's address. |
||
| 151 |
address addr; |
||
| 152 |
// The wallet's public key `X`. |
||
| 153 |
uint256 publicKeyX; |
||
| 154 |
// The wallet's public key `Y`. |
||
| 155 |
uint256 publicKeyY; |
||
| 156 |
// The wallet's private key. |
||
| 157 |
uint256 privateKey; |
||
| 158 |
} |
||
| 159 | |||
| 160 |
/// The result of a `tryFfi` call. |
||
| 161 |
struct FfiResult {
|
||
| 162 |
// The exit code of the call. |
||
| 163 |
int32 exitCode; |
||
| 164 |
// The optionally hex-decoded `stdout` data. |
||
| 165 |
bytes stdout; |
||
| 166 |
// The `stderr` data. |
||
| 167 |
bytes stderr; |
||
| 168 |
} |
||
| 169 | |||
| 170 |
/// Information on the chain and fork. |
||
| 171 |
struct ChainInfo {
|
||
| 172 |
// The fork identifier. Set to zero if no fork is active. |
||
| 173 |
uint256 forkId; |
||
| 174 |
// The chain ID of the current fork. |
||
| 175 |
uint256 chainId; |
||
| 176 |
} |
||
| 177 | |||
| 178 |
/// The result of a `stopAndReturnStateDiff` call. |
||
| 179 |
struct AccountAccess {
|
||
| 180 |
// The chain and fork the access occurred. |
||
| 181 |
ChainInfo chainInfo; |
||
| 182 |
// The kind of account access that determines what the account is. |
||
| 183 |
// If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee. |
||
| 184 |
// If kind is Create, then the account is the newly created account. |
||
| 185 |
// If kind is SelfDestruct, then the account is the selfdestruct recipient. |
||
| 186 |
// If kind is a Resume, then account represents a account context that has resumed. |
||
| 187 |
AccountAccessKind kind; |
||
| 188 |
// The account that was accessed. |
||
| 189 |
// It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT. |
||
| 190 |
address account; |
||
| 191 |
// What accessed the account. |
||
| 192 |
address accessor; |
||
| 193 |
// If the account was initialized or empty prior to the access. |
||
| 194 |
// An account is considered initialized if it has code, a |
||
| 195 |
// non-zero nonce, or a non-zero balance. |
||
| 196 |
bool initialized; |
||
| 197 |
// The previous balance of the accessed account. |
||
| 198 |
uint256 oldBalance; |
||
| 199 |
// The potential new balance of the accessed account. |
||
| 200 |
// That is, all balance changes are recorded here, even if reverts occurred. |
||
| 201 |
uint256 newBalance; |
||
| 202 |
// Code of the account deployed by CREATE. |
||
| 203 |
bytes deployedCode; |
||
| 204 |
// Value passed along with the account access |
||
| 205 |
uint256 value; |
||
| 206 |
// Input data provided to the CREATE or CALL |
||
| 207 |
bytes data; |
||
| 208 |
// If this access reverted in either the current or parent context. |
||
| 209 |
bool reverted; |
||
| 210 |
// An ordered list of storage accesses made during an account access operation. |
||
| 211 |
StorageAccess[] storageAccesses; |
||
| 212 |
// Call depth traversed during the recording of state differences |
||
| 213 |
uint64 depth; |
||
| 214 |
} |
||
| 215 | |||
| 216 |
/// The storage accessed during an `AccountAccess`. |
||
| 217 |
struct StorageAccess {
|
||
| 218 |
// The account whose storage was accessed. |
||
| 219 |
address account; |
||
| 220 |
// The slot that was accessed. |
||
| 221 |
bytes32 slot; |
||
| 222 |
// If the access was a write. |
||
| 223 |
bool isWrite; |
||
| 224 |
// The previous value of the slot. |
||
| 225 |
bytes32 previousValue; |
||
| 226 |
// The new value of the slot. |
||
| 227 |
bytes32 newValue; |
||
| 228 |
// If the access was reverted. |
||
| 229 |
bool reverted; |
||
| 230 |
} |
||
| 231 | |||
| 232 |
/// Gas used. Returned by `lastCallGas`. |
||
| 233 |
struct Gas {
|
||
| 234 |
// The gas limit of the call. |
||
| 235 |
uint64 gasLimit; |
||
| 236 |
// The total gas used. |
||
| 237 |
uint64 gasTotalUsed; |
||
| 238 |
// DEPRECATED: The amount of gas used for memory expansion. Ref: <https://github.com/foundry-rs/foundry/pull/7934#pullrequestreview-2069236939> |
||
| 239 |
uint64 gasMemoryUsed; |
||
| 240 |
// The amount of gas refunded. |
||
| 241 |
int64 gasRefunded; |
||
| 242 |
// The amount of gas remaining. |
||
| 243 |
uint64 gasRemaining; |
||
| 244 |
} |
||
| 245 | |||
| 246 |
// ======== Crypto ======== |
||
| 247 | |||
| 248 |
/// Derives a private key from the name, labels the account with that name, and returns the wallet. |
||
| 249 |
function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); |
||
| 250 | |||
| 251 |
/// Generates a wallet from the private key and returns the wallet. |
||
| 252 |
function createWallet(uint256 privateKey) external returns (Wallet memory wallet); |
||
| 253 | |||
| 254 |
/// Generates a wallet from the private key, labels the account with that name, and returns the wallet. |
||
| 255 |
function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); |
||
| 256 | |||
| 257 |
/// Derive a private key from a provided mnenomic string (or mnenomic file path) |
||
| 258 |
/// at the derivation path `m/44'/60'/0'/0/{index}`.
|
||
| 259 |
function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); |
||
| 260 | |||
| 261 |
/// Derive a private key from a provided mnenomic string (or mnenomic file path) |
||
| 262 |
/// at `{derivationPath}{index}`.
|
||
| 263 |
function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) |
||
| 264 |
external |
||
| 265 |
pure |
||
| 266 |
returns (uint256 privateKey); |
||
| 267 | |||
| 268 |
/// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language |
||
| 269 |
/// at the derivation path `m/44'/60'/0'/0/{index}`.
|
||
| 270 |
function deriveKey(string calldata mnemonic, uint32 index, string calldata language) |
||
| 271 |
external |
||
| 272 |
pure |
||
| 273 |
returns (uint256 privateKey); |
||
| 274 | |||
| 275 |
/// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language |
||
| 276 |
/// at `{derivationPath}{index}`.
|
||
| 277 |
function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) |
||
| 278 |
external |
||
| 279 |
pure |
||
| 280 |
returns (uint256 privateKey); |
||
| 281 | |||
| 282 |
/// Adds a private key to the local forge wallet and returns the address. |
||
| 283 |
function rememberKey(uint256 privateKey) external returns (address keyAddr); |
||
| 284 | |||
| 285 |
/// Signs data with a `Wallet`. |
||
| 286 |
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the |
||
| 287 |
/// signature's `s` value, and the recovery id `v` in a single bytes32. |
||
| 288 |
/// This format reduces the signature size from 65 to 64 bytes. |
||
| 289 |
function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); |
||
| 290 | |||
| 291 |
/// Signs `digest` with `privateKey` using the secp256k1 curve. |
||
| 292 |
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the |
||
| 293 |
/// signature's `s` value, and the recovery id `v` in a single bytes32. |
||
| 294 |
/// This format reduces the signature size from 65 to 64 bytes. |
||
| 295 |
function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); |
||
| 296 | |||
| 297 |
/// Signs `digest` with signer provided to script using the secp256k1 curve. |
||
| 298 |
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the |
||
| 299 |
/// signature's `s` value, and the recovery id `v` in a single bytes32. |
||
| 300 |
/// This format reduces the signature size from 65 to 64 bytes. |
||
| 301 |
/// If `--sender` is provided, the signer with provided address is used, otherwise, |
||
| 302 |
/// if exactly one signer is provided to the script, that signer is used. |
||
| 303 |
/// Raises error if signer passed through `--sender` does not match any unlocked signers or |
||
| 304 |
/// if `--sender` is not provided and not exactly one signer is passed to the script. |
||
| 305 |
function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); |
||
| 306 | |||
| 307 |
/// Signs `digest` with signer provided to script using the secp256k1 curve. |
||
| 308 |
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the |
||
| 309 |
/// signature's `s` value, and the recovery id `v` in a single bytes32. |
||
| 310 |
/// This format reduces the signature size from 65 to 64 bytes. |
||
| 311 |
/// Raises error if none of the signers passed into the script have provided address. |
||
| 312 |
function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); |
||
| 313 | |||
| 314 |
/// Signs `digest` with `privateKey` using the secp256r1 curve. |
||
| 315 |
function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); |
||
| 316 | |||
| 317 |
/// Signs data with a `Wallet`. |
||
| 318 |
function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); |
||
| 319 | |||
| 320 |
/// Signs `digest` with `privateKey` using the secp256k1 curve. |
||
| 321 |
function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); |
||
| 322 | |||
| 323 |
/// Signs `digest` with signer provided to script using the secp256k1 curve. |
||
| 324 |
/// If `--sender` is provided, the signer with provided address is used, otherwise, |
||
| 325 |
/// if exactly one signer is provided to the script, that signer is used. |
||
| 326 |
/// Raises error if signer passed through `--sender` does not match any unlocked signers or |
||
| 327 |
/// if `--sender` is not provided and not exactly one signer is passed to the script. |
||
| 328 |
function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); |
||
| 329 | |||
| 330 |
/// Signs `digest` with signer provided to script using the secp256k1 curve. |
||
| 331 |
/// Raises error if none of the signers passed into the script have provided address. |
||
| 332 |
function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); |
||
| 333 | |||
| 334 |
// ======== Environment ======== |
||
| 335 | |||
| 336 |
/// Gets the environment variable `name` and parses it as `address`. |
||
| 337 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 338 |
function envAddress(string calldata name) external view returns (address value); |
||
| 339 | |||
| 340 |
/// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. |
||
| 341 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 342 |
function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); |
||
| 343 | |||
| 344 |
/// Gets the environment variable `name` and parses it as `bool`. |
||
| 345 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 346 |
function envBool(string calldata name) external view returns (bool value); |
||
| 347 | |||
| 348 |
/// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. |
||
| 349 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 350 |
function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value); |
||
| 351 | |||
| 352 |
/// Gets the environment variable `name` and parses it as `bytes32`. |
||
| 353 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 354 |
function envBytes32(string calldata name) external view returns (bytes32 value); |
||
| 355 | |||
| 356 |
/// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. |
||
| 357 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 358 |
function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value); |
||
| 359 | |||
| 360 |
/// Gets the environment variable `name` and parses it as `bytes`. |
||
| 361 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 362 |
function envBytes(string calldata name) external view returns (bytes memory value); |
||
| 363 | |||
| 364 |
/// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. |
||
| 365 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 366 |
function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value); |
||
| 367 | |||
| 368 |
/// Gets the environment variable `name` and returns true if it exists, else returns false. |
||
| 369 |
function envExists(string calldata name) external view returns (bool result); |
||
| 370 | |||
| 371 |
/// Gets the environment variable `name` and parses it as `int256`. |
||
| 372 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 373 |
function envInt(string calldata name) external view returns (int256 value); |
||
| 374 | |||
| 375 |
/// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. |
||
| 376 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 377 |
function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value); |
||
| 378 | |||
| 379 |
/// Gets the environment variable `name` and parses it as `bool`. |
||
| 380 |
/// Reverts if the variable could not be parsed. |
||
| 381 |
/// Returns `defaultValue` if the variable was not found. |
||
| 382 |
function envOr(string calldata name, bool defaultValue) external view returns (bool value); |
||
| 383 | |||
| 384 |
/// Gets the environment variable `name` and parses it as `uint256`. |
||
| 385 |
/// Reverts if the variable could not be parsed. |
||
| 386 |
/// Returns `defaultValue` if the variable was not found. |
||
| 387 |
function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value); |
||
| 388 | |||
| 389 |
/// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. |
||
| 390 |
/// Reverts if the variable could not be parsed. |
||
| 391 |
/// Returns `defaultValue` if the variable was not found. |
||
| 392 |
function envOr(string calldata name, string calldata delim, address[] calldata defaultValue) |
||
| 393 |
external |
||
| 394 |
view |
||
| 395 |
returns (address[] memory value); |
||
| 396 | |||
| 397 |
/// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. |
||
| 398 |
/// Reverts if the variable could not be parsed. |
||
| 399 |
/// Returns `defaultValue` if the variable was not found. |
||
| 400 |
function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue) |
||
| 401 |
external |
||
| 402 |
view |
||
| 403 |
returns (bytes32[] memory value); |
||
| 404 | |||
| 405 |
/// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. |
||
| 406 |
/// Reverts if the variable could not be parsed. |
||
| 407 |
/// Returns `defaultValue` if the variable was not found. |
||
| 408 |
function envOr(string calldata name, string calldata delim, string[] calldata defaultValue) |
||
| 409 |
external |
||
| 410 |
view |
||
| 411 |
returns (string[] memory value); |
||
| 412 | |||
| 413 |
/// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. |
||
| 414 |
/// Reverts if the variable could not be parsed. |
||
| 415 |
/// Returns `defaultValue` if the variable was not found. |
||
| 416 |
function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue) |
||
| 417 |
external |
||
| 418 |
view |
||
| 419 |
returns (bytes[] memory value); |
||
| 420 | |||
| 421 |
/// Gets the environment variable `name` and parses it as `int256`. |
||
| 422 |
/// Reverts if the variable could not be parsed. |
||
| 423 |
/// Returns `defaultValue` if the variable was not found. |
||
| 424 |
function envOr(string calldata name, int256 defaultValue) external view returns (int256 value); |
||
| 425 | |||
| 426 |
/// Gets the environment variable `name` and parses it as `address`. |
||
| 427 |
/// Reverts if the variable could not be parsed. |
||
| 428 |
/// Returns `defaultValue` if the variable was not found. |
||
| 429 |
function envOr(string calldata name, address defaultValue) external view returns (address value); |
||
| 430 | |||
| 431 |
/// Gets the environment variable `name` and parses it as `bytes32`. |
||
| 432 |
/// Reverts if the variable could not be parsed. |
||
| 433 |
/// Returns `defaultValue` if the variable was not found. |
||
| 434 |
function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value); |
||
| 435 | |||
| 436 |
/// Gets the environment variable `name` and parses it as `string`. |
||
| 437 |
/// Reverts if the variable could not be parsed. |
||
| 438 |
/// Returns `defaultValue` if the variable was not found. |
||
| 439 |
function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value); |
||
| 440 | |||
| 441 |
/// Gets the environment variable `name` and parses it as `bytes`. |
||
| 442 |
/// Reverts if the variable could not be parsed. |
||
| 443 |
/// Returns `defaultValue` if the variable was not found. |
||
| 444 |
function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value); |
||
| 445 | |||
| 446 |
/// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. |
||
| 447 |
/// Reverts if the variable could not be parsed. |
||
| 448 |
/// Returns `defaultValue` if the variable was not found. |
||
| 449 |
function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue) |
||
| 450 |
external |
||
| 451 |
view |
||
| 452 |
returns (bool[] memory value); |
||
| 453 | |||
| 454 |
/// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. |
||
| 455 |
/// Reverts if the variable could not be parsed. |
||
| 456 |
/// Returns `defaultValue` if the variable was not found. |
||
| 457 |
function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue) |
||
| 458 |
external |
||
| 459 |
view |
||
| 460 |
returns (uint256[] memory value); |
||
| 461 | |||
| 462 |
/// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. |
||
| 463 |
/// Reverts if the variable could not be parsed. |
||
| 464 |
/// Returns `defaultValue` if the variable was not found. |
||
| 465 |
function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue) |
||
| 466 |
external |
||
| 467 |
view |
||
| 468 |
returns (int256[] memory value); |
||
| 469 | |||
| 470 |
/// Gets the environment variable `name` and parses it as `string`. |
||
| 471 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 472 |
function envString(string calldata name) external view returns (string memory value); |
||
| 473 | |||
| 474 |
/// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. |
||
| 475 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 476 |
function envString(string calldata name, string calldata delim) external view returns (string[] memory value); |
||
| 477 | |||
| 478 |
/// Gets the environment variable `name` and parses it as `uint256`. |
||
| 479 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 480 |
function envUint(string calldata name) external view returns (uint256 value); |
||
| 481 | |||
| 482 |
/// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. |
||
| 483 |
/// Reverts if the variable was not found or could not be parsed. |
||
| 484 |
function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); |
||
| 485 | |||
| 486 |
/// Returns true if `forge` command was executed in given context. |
||
| 487 |
function isContext(ForgeContext context) external view returns (bool result); |
||
| 488 | |||
| 489 |
/// Sets environment variables. |
||
| 490 |
function setEnv(string calldata name, string calldata value) external; |
||
| 491 | |||
| 492 |
// ======== EVM ======== |
||
| 493 | |||
| 494 |
/// Gets all accessed reads and write slot from a `vm.record` session, for a given address. |
||
| 495 |
function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots); |
||
| 496 | |||
| 497 |
/// Gets the address for a given private key. |
||
| 498 |
function addr(uint256 privateKey) external pure returns (address keyAddr); |
||
| 499 | |||
| 500 |
/// Gets all the logs according to specified filter. |
||
| 501 |
function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) |
||
| 502 |
external |
||
| 503 |
returns (EthGetLogs[] memory logs); |
||
| 504 | |||
| 505 |
/// Gets the current `block.blobbasefee`. |
||
| 506 |
/// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction, |
||
| 507 |
/// and as a result will get optimized out by the compiler. |
||
| 508 |
/// See https://github.com/foundry-rs/foundry/issues/6180 |
||
| 509 |
function getBlobBaseFee() external view returns (uint256 blobBaseFee); |
||
| 510 | |||
| 511 |
/// Gets the current `block.number`. |
||
| 512 |
/// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction, |
||
| 513 |
/// and as a result will get optimized out by the compiler. |
||
| 514 |
/// See https://github.com/foundry-rs/foundry/issues/6180 |
||
| 515 |
function getBlockNumber() external view returns (uint256 height); |
||
| 516 | |||
| 517 |
/// Gets the current `block.timestamp`. |
||
| 518 |
/// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction, |
||
| 519 |
/// and as a result will get optimized out by the compiler. |
||
| 520 |
/// See https://github.com/foundry-rs/foundry/issues/6180 |
||
| 521 |
function getBlockTimestamp() external view returns (uint256 timestamp); |
||
| 522 | |||
| 523 |
/// Gets the map key and parent of a mapping at a given slot, for a given address. |
||
| 524 |
function getMappingKeyAndParentOf(address target, bytes32 elementSlot) |
||
| 525 |
external |
||
| 526 |
returns (bool found, bytes32 key, bytes32 parent); |
||
| 527 | |||
| 528 |
/// Gets the number of elements in the mapping at the given slot, for a given address. |
||
| 529 |
function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length); |
||
| 530 | |||
| 531 |
/// Gets the elements at index idx of the mapping at the given slot, for a given address. The |
||
| 532 |
/// index must be less than the length of the mapping (i.e. the number of keys in the mapping). |
||
| 533 |
function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value); |
||
| 534 | |||
| 535 |
/// Gets the nonce of an account. |
||
| 536 |
function getNonce(address account) external view returns (uint64 nonce); |
||
| 537 | |||
| 538 |
/// Get the nonce of a `Wallet`. |
||
| 539 |
function getNonce(Wallet calldata wallet) external returns (uint64 nonce); |
||
| 540 | |||
| 541 |
/// Gets all the recorded logs. |
||
| 542 |
function getRecordedLogs() external returns (Log[] memory logs); |
||
| 543 | |||
| 544 |
/// Gets the gas used in the last call. |
||
| 545 |
function lastCallGas() external view returns (Gas memory gas); |
||
| 546 | |||
| 547 |
/// Loads a storage slot from an address. |
||
| 548 |
function load(address target, bytes32 slot) external view returns (bytes32 data); |
||
| 549 | |||
| 550 |
/// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused. |
||
| 551 |
function pauseGasMetering() external; |
||
| 552 | |||
| 553 |
/// Records all storage reads and writes. |
||
| 554 |
function record() external; |
||
| 555 | |||
| 556 |
/// Record all the transaction logs. |
||
| 557 |
function recordLogs() external; |
||
| 558 | |||
| 559 |
/// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. |
||
| 560 |
function resumeGasMetering() external; |
||
| 561 | |||
| 562 |
/// Performs an Ethereum JSON-RPC request to the current fork URL. |
||
| 563 |
function rpc(string calldata method, string calldata params) external returns (bytes memory data); |
||
| 564 | |||
| 565 |
/// Performs an Ethereum JSON-RPC request to the given endpoint. |
||
| 566 |
function rpc(string calldata urlOrAlias, string calldata method, string calldata params) |
||
| 567 |
external |
||
| 568 |
returns (bytes memory data); |
||
| 569 | |||
| 570 |
/// Starts recording all map SSTOREs for later retrieval. |
||
| 571 |
function startMappingRecording() external; |
||
| 572 | |||
| 573 |
/// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order, |
||
| 574 |
/// along with the context of the calls |
||
| 575 |
function startStateDiffRecording() external; |
||
| 576 | |||
| 577 |
/// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. |
||
| 578 |
function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); |
||
| 579 | |||
| 580 |
/// Stops recording all map SSTOREs for later retrieval and clears the recorded data. |
||
| 581 |
function stopMappingRecording() external; |
||
| 582 | |||
| 583 |
// ======== Filesystem ======== |
||
| 584 | |||
| 585 |
/// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. |
||
| 586 |
/// `path` is relative to the project root. |
||
| 587 |
function closeFile(string calldata path) external; |
||
| 588 | |||
| 589 |
/// Copies the contents of one file to another. This function will **overwrite** the contents of `to`. |
||
| 590 |
/// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`. |
||
| 591 |
/// Both `from` and `to` are relative to the project root. |
||
| 592 |
function copyFile(string calldata from, string calldata to) external returns (uint64 copied); |
||
| 593 | |||
| 594 |
/// Creates a new, empty directory at the provided path. |
||
| 595 |
/// This cheatcode will revert in the following situations, but is not limited to just these cases: |
||
| 596 |
/// - User lacks permissions to modify `path`. |
||
| 597 |
/// - A parent of the given path doesn't exist and `recursive` is false. |
||
| 598 |
/// - `path` already exists and `recursive` is false. |
||
| 599 |
/// `path` is relative to the project root. |
||
| 600 |
function createDir(string calldata path, bool recursive) external; |
||
| 601 | |||
| 602 |
/// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the |
||
| 603 |
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. |
||
| 604 |
function deployCode(string calldata artifactPath) external returns (address deployedAddress); |
||
| 605 | |||
| 606 |
/// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the |
||
| 607 |
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. |
||
| 608 |
/// Additionaly accepts abi-encoded constructor arguments. |
||
| 609 |
function deployCode(string calldata artifactPath, bytes calldata constructorArgs) |
||
| 610 |
external |
||
| 611 |
returns (address deployedAddress); |
||
| 612 | |||
| 613 |
/// Returns true if the given path points to an existing entity, else returns false. |
||
| 614 |
function exists(string calldata path) external returns (bool result); |
||
| 615 | |||
| 616 |
/// Performs a foreign function call via the terminal. |
||
| 617 |
function ffi(string[] calldata commandInput) external returns (bytes memory result); |
||
| 618 | |||
| 619 |
/// Given a path, query the file system to get information about a file, directory, etc. |
||
| 620 |
function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); |
||
| 621 | |||
| 622 |
/// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the |
||
| 623 |
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. |
||
| 624 |
function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); |
||
| 625 | |||
| 626 |
/// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the |
||
| 627 |
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. |
||
| 628 |
function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); |
||
| 629 | |||
| 630 |
/// Returns true if the path exists on disk and is pointing at a directory, else returns false. |
||
| 631 |
function isDir(string calldata path) external returns (bool result); |
||
| 632 | |||
| 633 |
/// Returns true if the path exists on disk and is pointing at a regular file, else returns false. |
||
| 634 |
function isFile(string calldata path) external returns (bool result); |
||
| 635 | |||
| 636 |
/// Get the path of the current project root. |
||
| 637 |
function projectRoot() external view returns (string memory path); |
||
| 638 | |||
| 639 |
/// Prompts the user for a string value in the terminal. |
||
| 640 |
function prompt(string calldata promptText) external returns (string memory input); |
||
| 641 | |||
| 642 |
/// Prompts the user for an address in the terminal. |
||
| 643 |
function promptAddress(string calldata promptText) external returns (address); |
||
| 644 | |||
| 645 |
/// Prompts the user for a hidden string value in the terminal. |
||
| 646 |
function promptSecret(string calldata promptText) external returns (string memory input); |
||
| 647 | |||
| 648 |
/// Prompts the user for hidden uint256 in the terminal (usually pk). |
||
| 649 |
function promptSecretUint(string calldata promptText) external returns (uint256); |
||
| 650 | |||
| 651 |
/// Prompts the user for uint256 in the terminal. |
||
| 652 |
function promptUint(string calldata promptText) external returns (uint256); |
||
| 653 | |||
| 654 |
/// Reads the directory at the given path recursively, up to `maxDepth`. |
||
| 655 |
/// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned. |
||
| 656 |
/// Follows symbolic links if `followLinks` is true. |
||
| 657 |
function readDir(string calldata path) external view returns (DirEntry[] memory entries); |
||
| 658 | |||
| 659 |
/// See `readDir(string)`. |
||
| 660 |
function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries); |
||
| 661 | |||
| 662 |
/// See `readDir(string)`. |
||
| 663 |
function readDir(string calldata path, uint64 maxDepth, bool followLinks) |
||
| 664 |
external |
||
| 665 |
view |
||
| 666 |
returns (DirEntry[] memory entries); |
||
| 667 | |||
| 668 |
/// Reads the entire content of file to string. `path` is relative to the project root. |
||
| 669 |
function readFile(string calldata path) external view returns (string memory data); |
||
| 670 | |||
| 671 |
/// Reads the entire content of file as binary. `path` is relative to the project root. |
||
| 672 |
function readFileBinary(string calldata path) external view returns (bytes memory data); |
||
| 673 | |||
| 674 |
/// Reads next line of file to string. |
||
| 675 |
function readLine(string calldata path) external view returns (string memory line); |
||
| 676 | |||
| 677 |
/// Reads a symbolic link, returning the path that the link points to. |
||
| 678 |
/// This cheatcode will revert in the following situations, but is not limited to just these cases: |
||
| 679 |
/// - `path` is not a symbolic link. |
||
| 680 |
/// - `path` does not exist. |
||
| 681 |
function readLink(string calldata linkPath) external view returns (string memory targetPath); |
||
| 682 | |||
| 683 |
/// Removes a directory at the provided path. |
||
| 684 |
/// This cheatcode will revert in the following situations, but is not limited to just these cases: |
||
| 685 |
/// - `path` doesn't exist. |
||
| 686 |
/// - `path` isn't a directory. |
||
| 687 |
/// - User lacks permissions to modify `path`. |
||
| 688 |
/// - The directory is not empty and `recursive` is false. |
||
| 689 |
/// `path` is relative to the project root. |
||
| 690 |
function removeDir(string calldata path, bool recursive) external; |
||
| 691 | |||
| 692 |
/// Removes a file from the filesystem. |
||
| 693 |
/// This cheatcode will revert in the following situations, but is not limited to just these cases: |
||
| 694 |
/// - `path` points to a directory. |
||
| 695 |
/// - The file doesn't exist. |
||
| 696 |
/// - The user lacks permissions to remove the file. |
||
| 697 |
/// `path` is relative to the project root. |
||
| 698 |
function removeFile(string calldata path) external; |
||
| 699 | |||
| 700 |
/// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr. |
||
| 701 |
function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); |
||
| 702 | |||
| 703 |
/// Returns the time since unix epoch in milliseconds. |
||
| 704 |
function unixTime() external returns (uint256 milliseconds); |
||
| 705 | |||
| 706 |
/// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. |
||
| 707 |
/// `path` is relative to the project root. |
||
| 708 |
function writeFile(string calldata path, string calldata data) external; |
||
| 709 | |||
| 710 |
/// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. |
||
| 711 |
/// `path` is relative to the project root. |
||
| 712 |
function writeFileBinary(string calldata path, bytes calldata data) external; |
||
| 713 | |||
| 714 |
/// Writes line to file, creating a file if it does not exist. |
||
| 715 |
/// `path` is relative to the project root. |
||
| 716 |
function writeLine(string calldata path, string calldata data) external; |
||
| 717 | |||
| 718 |
// ======== JSON ======== |
||
| 719 | |||
| 720 |
/// Checks if `key` exists in a JSON object |
||
| 721 |
/// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. |
||
| 722 |
function keyExists(string calldata json, string calldata key) external view returns (bool); |
||
| 723 | |||
| 724 |
/// Checks if `key` exists in a JSON object. |
||
| 725 |
function keyExistsJson(string calldata json, string calldata key) external view returns (bool); |
||
| 726 | |||
| 727 |
/// Parses a string of JSON data at `key` and coerces it to `address`. |
||
| 728 |
function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); |
||
| 729 | |||
| 730 |
/// Parses a string of JSON data at `key` and coerces it to `address[]`. |
||
| 731 |
function parseJsonAddressArray(string calldata json, string calldata key) |
||
| 732 |
external |
||
| 733 |
pure |
||
| 734 |
returns (address[] memory); |
||
| 735 | |||
| 736 |
/// Parses a string of JSON data at `key` and coerces it to `bool`. |
||
| 737 |
function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); |
||
| 738 | |||
| 739 |
/// Parses a string of JSON data at `key` and coerces it to `bool[]`. |
||
| 740 |
function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory); |
||
| 741 | |||
| 742 |
/// Parses a string of JSON data at `key` and coerces it to `bytes`. |
||
| 743 |
function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory); |
||
| 744 | |||
| 745 |
/// Parses a string of JSON data at `key` and coerces it to `bytes32`. |
||
| 746 |
function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); |
||
| 747 | |||
| 748 |
/// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. |
||
| 749 |
function parseJsonBytes32Array(string calldata json, string calldata key) |
||
| 750 |
external |
||
| 751 |
pure |
||
| 752 |
returns (bytes32[] memory); |
||
| 753 | |||
| 754 |
/// Parses a string of JSON data at `key` and coerces it to `bytes[]`. |
||
| 755 |
function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); |
||
| 756 | |||
| 757 |
/// Parses a string of JSON data at `key` and coerces it to `int256`. |
||
| 758 |
function parseJsonInt(string calldata json, string calldata key) external pure returns (int256); |
||
| 759 | |||
| 760 |
/// Parses a string of JSON data at `key` and coerces it to `int256[]`. |
||
| 761 |
function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory); |
||
| 762 | |||
| 763 |
/// Returns an array of all the keys in a JSON object. |
||
| 764 |
function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); |
||
| 765 | |||
| 766 |
/// Parses a string of JSON data at `key` and coerces it to `string`. |
||
| 767 |
function parseJsonString(string calldata json, string calldata key) external pure returns (string memory); |
||
| 768 | |||
| 769 |
/// Parses a string of JSON data at `key` and coerces it to `string[]`. |
||
| 770 |
function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); |
||
| 771 | |||
| 772 |
/// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`. |
||
| 773 |
function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription) |
||
| 774 |
external |
||
| 775 |
pure |
||
| 776 |
returns (bytes memory); |
||
| 777 | |||
| 778 |
/// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. |
||
| 779 |
function parseJsonType(string calldata json, string calldata typeDescription) |
||
| 780 |
external |
||
| 781 |
pure |
||
| 782 |
returns (bytes memory); |
||
| 783 | |||
| 784 |
/// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. |
||
| 785 |
function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) |
||
| 786 |
external |
||
| 787 |
pure |
||
| 788 |
returns (bytes memory); |
||
| 789 | |||
| 790 |
/// Parses a string of JSON data at `key` and coerces it to `uint256`. |
||
| 791 |
function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); |
||
| 792 | |||
| 793 |
/// Parses a string of JSON data at `key` and coerces it to `uint256[]`. |
||
| 794 |
function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory); |
||
| 795 | |||
| 796 |
/// ABI-encodes a JSON object. |
||
| 797 |
function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData); |
||
| 798 | |||
| 799 |
/// ABI-encodes a JSON object at `key`. |
||
| 800 |
function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData); |
||
| 801 | |||
| 802 |
/// See `serializeJson`. |
||
| 803 |
function serializeAddress(string calldata objectKey, string calldata valueKey, address value) |
||
| 804 |
external |
||
| 805 |
returns (string memory json); |
||
| 806 | |||
| 807 |
/// See `serializeJson`. |
||
| 808 |
function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values) |
||
| 809 |
external |
||
| 810 |
returns (string memory json); |
||
| 811 | |||
| 812 |
/// See `serializeJson`. |
||
| 813 |
function serializeBool(string calldata objectKey, string calldata valueKey, bool value) |
||
| 814 |
external |
||
| 815 |
returns (string memory json); |
||
| 816 | |||
| 817 |
/// See `serializeJson`. |
||
| 818 |
function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values) |
||
| 819 |
external |
||
| 820 |
returns (string memory json); |
||
| 821 | |||
| 822 |
/// See `serializeJson`. |
||
| 823 |
function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value) |
||
| 824 |
external |
||
| 825 |
returns (string memory json); |
||
| 826 | |||
| 827 |
/// See `serializeJson`. |
||
| 828 |
function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values) |
||
| 829 |
external |
||
| 830 |
returns (string memory json); |
||
| 831 | |||
| 832 |
/// See `serializeJson`. |
||
| 833 |
function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value) |
||
| 834 |
external |
||
| 835 |
returns (string memory json); |
||
| 836 | |||
| 837 |
/// See `serializeJson`. |
||
| 838 |
function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values) |
||
| 839 |
external |
||
| 840 |
returns (string memory json); |
||
| 841 | |||
| 842 |
/// See `serializeJson`. |
||
| 843 |
function serializeInt(string calldata objectKey, string calldata valueKey, int256 value) |
||
| 844 |
external |
||
| 845 |
returns (string memory json); |
||
| 846 | |||
| 847 |
/// See `serializeJson`. |
||
| 848 |
function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values) |
||
| 849 |
external |
||
| 850 |
returns (string memory json); |
||
| 851 | |||
| 852 |
/// Serializes a key and value to a JSON object stored in-memory that can be later written to a file. |
||
| 853 |
/// Returns the stringified version of the specific JSON file up to that moment. |
||
| 854 |
function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); |
||
| 855 | |||
| 856 |
/// See `serializeJson`. |
||
| 857 |
function serializeJsonType(string calldata typeDescription, bytes calldata value) |
||
| 858 |
external |
||
| 859 |
pure |
||
| 860 |
returns (string memory json); |
||
| 861 | |||
| 862 |
/// See `serializeJson`. |
||
| 863 |
function serializeJsonType( |
||
| 864 |
string calldata objectKey, |
||
| 865 |
string calldata valueKey, |
||
| 866 |
string calldata typeDescription, |
||
| 867 |
bytes calldata value |
||
| 868 |
) external returns (string memory json); |
||
| 869 | |||
| 870 |
/// See `serializeJson`. |
||
| 871 |
function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) |
||
| 872 |
external |
||
| 873 |
returns (string memory json); |
||
| 874 | |||
| 875 |
/// See `serializeJson`. |
||
| 876 |
function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values) |
||
| 877 |
external |
||
| 878 |
returns (string memory json); |
||
| 879 | |||
| 880 |
/// See `serializeJson`. |
||
| 881 |
function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value) |
||
| 882 |
external |
||
| 883 |
returns (string memory json); |
||
| 884 | |||
| 885 |
/// See `serializeJson`. |
||
| 886 |
function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value) |
||
| 887 |
external |
||
| 888 |
returns (string memory json); |
||
| 889 | |||
| 890 |
/// See `serializeJson`. |
||
| 891 |
function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values) |
||
| 892 |
external |
||
| 893 |
returns (string memory json); |
||
| 894 | |||
| 895 |
/// Write a serialized JSON object to a file. If the file exists, it will be overwritten. |
||
| 896 |
function writeJson(string calldata json, string calldata path) external; |
||
| 897 | |||
| 898 |
/// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key.> |
||
| 899 |
/// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. |
||
| 900 |
function writeJson(string calldata json, string calldata path, string calldata valueKey) external; |
||
| 901 | |||
| 902 |
// ======== Scripting ======== |
||
| 903 | |||
| 904 |
/// Takes a signed transaction and broadcasts it to the network. |
||
| 905 |
function broadcastRawTransaction(bytes calldata data) external; |
||
| 906 | |||
| 907 |
/// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. |
||
| 908 |
/// Broadcasting address is determined by checking the following in order: |
||
| 909 |
/// 1. If `--sender` argument was provided, that address is used. |
||
| 910 |
/// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. |
||
| 911 |
/// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. |
||
| 912 |
function broadcast() external; |
||
| 913 | |||
| 914 |
/// Has the next call (at this call depth only) create a transaction with the address provided |
||
| 915 |
/// as the sender that can later be signed and sent onchain. |
||
| 916 |
function broadcast(address signer) external; |
||
| 917 | |||
| 918 |
/// Has the next call (at this call depth only) create a transaction with the private key |
||
| 919 |
/// provided as the sender that can later be signed and sent onchain. |
||
| 920 |
function broadcast(uint256 privateKey) external; |
||
| 921 | |||
| 922 |
/// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. |
||
| 923 |
/// Broadcasting address is determined by checking the following in order: |
||
| 924 |
/// 1. If `--sender` argument was provided, that address is used. |
||
| 925 |
/// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. |
||
| 926 |
/// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. |
||
| 927 |
function startBroadcast() external; |
||
| 928 | |||
| 929 |
/// Has all subsequent calls (at this call depth only) create transactions with the address |
||
| 930 |
/// provided that can later be signed and sent onchain. |
||
| 931 |
function startBroadcast(address signer) external; |
||
| 932 | |||
| 933 |
/// Has all subsequent calls (at this call depth only) create transactions with the private key |
||
| 934 |
/// provided that can later be signed and sent onchain. |
||
| 935 |
function startBroadcast(uint256 privateKey) external; |
||
| 936 | |||
| 937 |
/// Stops collecting onchain transactions. |
||
| 938 |
function stopBroadcast() external; |
||
| 939 | |||
| 940 |
// ======== String ======== |
||
| 941 | |||
| 942 |
/// Returns the index of the first occurrence of a `key` in an `input` string. |
||
| 943 |
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found. |
||
| 944 |
/// Returns 0 in case of an empty `key`. |
||
| 945 |
function indexOf(string calldata input, string calldata key) external pure returns (uint256); |
||
| 946 | |||
| 947 |
/// Parses the given `string` into an `address`. |
||
| 948 |
function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue); |
||
| 949 | |||
| 950 |
/// Parses the given `string` into a `bool`. |
||
| 951 |
function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue); |
||
| 952 | |||
| 953 |
/// Parses the given `string` into `bytes`. |
||
| 954 |
function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue); |
||
| 955 | |||
| 956 |
/// Parses the given `string` into a `bytes32`. |
||
| 957 |
function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue); |
||
| 958 | |||
| 959 |
/// Parses the given `string` into a `int256`. |
||
| 960 |
function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue); |
||
| 961 | |||
| 962 |
/// Parses the given `string` into a `uint256`. |
||
| 963 |
function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue); |
||
| 964 | |||
| 965 |
/// Replaces occurrences of `from` in the given `string` with `to`. |
||
| 966 |
function replace(string calldata input, string calldata from, string calldata to) |
||
| 967 |
external |
||
| 968 |
pure |
||
| 969 |
returns (string memory output); |
||
| 970 | |||
| 971 |
/// Splits the given `string` into an array of strings divided by the `delimiter`. |
||
| 972 |
function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); |
||
| 973 | |||
| 974 |
/// Converts the given `string` value to Lowercase. |
||
| 975 |
function toLowercase(string calldata input) external pure returns (string memory output); |
||
| 976 | |||
| 977 |
/// Converts the given value to a `string`. |
||
| 978 |
function toString(address value) external pure returns (string memory stringifiedValue); |
||
| 979 | |||
| 980 |
/// Converts the given value to a `string`. |
||
| 981 |
function toString(bytes calldata value) external pure returns (string memory stringifiedValue); |
||
| 982 | |||
| 983 |
/// Converts the given value to a `string`. |
||
| 984 |
function toString(bytes32 value) external pure returns (string memory stringifiedValue); |
||
| 985 | |||
| 986 |
/// Converts the given value to a `string`. |
||
| 987 |
function toString(bool value) external pure returns (string memory stringifiedValue); |
||
| 988 | |||
| 989 |
/// Converts the given value to a `string`. |
||
| 990 |
function toString(uint256 value) external pure returns (string memory stringifiedValue); |
||
| 991 | |||
| 992 |
/// Converts the given value to a `string`. |
||
| 993 |
function toString(int256 value) external pure returns (string memory stringifiedValue); |
||
| 994 | |||
| 995 |
/// Converts the given `string` value to Uppercase. |
||
| 996 |
function toUppercase(string calldata input) external pure returns (string memory output); |
||
| 997 | |||
| 998 |
/// Trims leading and trailing whitespace from the given `string` value. |
||
| 999 |
function trim(string calldata input) external pure returns (string memory output); |
||
| 1000 | |||
| 1001 |
// ======== Testing ======== |
||
| 1002 | |||
| 1003 |
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1004 |
/// Formats values with decimals in failure message. |
||
| 1005 |
function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; |
||
| 1006 | |||
| 1007 |
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1008 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1009 |
function assertApproxEqAbsDecimal( |
||
| 1010 |
uint256 left, |
||
| 1011 |
uint256 right, |
||
| 1012 |
uint256 maxDelta, |
||
| 1013 |
uint256 decimals, |
||
| 1014 |
string calldata error |
||
| 1015 |
) external pure; |
||
| 1016 | |||
| 1017 |
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1018 |
/// Formats values with decimals in failure message. |
||
| 1019 |
function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; |
||
| 1020 | |||
| 1021 |
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1022 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1023 |
function assertApproxEqAbsDecimal( |
||
| 1024 |
int256 left, |
||
| 1025 |
int256 right, |
||
| 1026 |
uint256 maxDelta, |
||
| 1027 |
uint256 decimals, |
||
| 1028 |
string calldata error |
||
| 1029 |
) external pure; |
||
| 1030 | |||
| 1031 |
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1032 |
function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; |
||
| 1033 | |||
| 1034 |
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1035 |
/// Includes error message into revert string on failure. |
||
| 1036 |
function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; |
||
| 1037 | |||
| 1038 |
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1039 |
function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; |
||
| 1040 | |||
| 1041 |
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. |
||
| 1042 |
/// Includes error message into revert string on failure. |
||
| 1043 |
function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; |
||
| 1044 | |||
| 1045 |
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1046 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1047 |
/// Formats values with decimals in failure message. |
||
| 1048 |
function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) |
||
| 1049 |
external |
||
| 1050 |
pure; |
||
| 1051 | |||
| 1052 |
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1053 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1054 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1055 |
function assertApproxEqRelDecimal( |
||
| 1056 |
uint256 left, |
||
| 1057 |
uint256 right, |
||
| 1058 |
uint256 maxPercentDelta, |
||
| 1059 |
uint256 decimals, |
||
| 1060 |
string calldata error |
||
| 1061 |
) external pure; |
||
| 1062 | |||
| 1063 |
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1064 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1065 |
/// Formats values with decimals in failure message. |
||
| 1066 |
function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) |
||
| 1067 |
external |
||
| 1068 |
pure; |
||
| 1069 | |||
| 1070 |
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1071 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1072 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1073 |
function assertApproxEqRelDecimal( |
||
| 1074 |
int256 left, |
||
| 1075 |
int256 right, |
||
| 1076 |
uint256 maxPercentDelta, |
||
| 1077 |
uint256 decimals, |
||
| 1078 |
string calldata error |
||
| 1079 |
) external pure; |
||
| 1080 | |||
| 1081 |
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1082 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1083 |
function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; |
||
| 1084 | |||
| 1085 |
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1086 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1087 |
/// Includes error message into revert string on failure. |
||
| 1088 |
function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) |
||
| 1089 |
external |
||
| 1090 |
pure; |
||
| 1091 | |||
| 1092 |
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1093 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1094 |
function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; |
||
| 1095 | |||
| 1096 |
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. |
||
| 1097 |
/// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% |
||
| 1098 |
/// Includes error message into revert string on failure. |
||
| 1099 |
function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) |
||
| 1100 |
external |
||
| 1101 |
pure; |
||
| 1102 | |||
| 1103 |
/// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. |
||
| 1104 |
function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; |
||
| 1105 | |||
| 1106 |
/// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. |
||
| 1107 |
/// Includes error message into revert string on failure. |
||
| 1108 |
function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; |
||
| 1109 | |||
| 1110 |
/// Asserts that two `int256` values are equal, formatting them with decimals in failure message. |
||
| 1111 |
function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; |
||
| 1112 | |||
| 1113 |
/// Asserts that two `int256` values are equal, formatting them with decimals in failure message. |
||
| 1114 |
/// Includes error message into revert string on failure. |
||
| 1115 |
function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; |
||
| 1116 | |||
| 1117 |
/// Asserts that two `bool` values are equal. |
||
| 1118 |
function assertEq(bool left, bool right) external pure; |
||
| 1119 | |||
| 1120 |
/// Asserts that two `bool` values are equal and includes error message into revert string on failure. |
||
| 1121 |
function assertEq(bool left, bool right, string calldata error) external pure; |
||
| 1122 | |||
| 1123 |
/// Asserts that two `string` values are equal. |
||
| 1124 |
function assertEq(string calldata left, string calldata right) external pure; |
||
| 1125 | |||
| 1126 |
/// Asserts that two `string` values are equal and includes error message into revert string on failure. |
||
| 1127 |
function assertEq(string calldata left, string calldata right, string calldata error) external pure; |
||
| 1128 | |||
| 1129 |
/// Asserts that two `bytes` values are equal. |
||
| 1130 |
function assertEq(bytes calldata left, bytes calldata right) external pure; |
||
| 1131 | |||
| 1132 |
/// Asserts that two `bytes` values are equal and includes error message into revert string on failure. |
||
| 1133 |
function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; |
||
| 1134 | |||
| 1135 |
/// Asserts that two arrays of `bool` values are equal. |
||
| 1136 |
function assertEq(bool[] calldata left, bool[] calldata right) external pure; |
||
| 1137 | |||
| 1138 |
/// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. |
||
| 1139 |
function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; |
||
| 1140 | |||
| 1141 |
/// Asserts that two arrays of `uint256 values are equal. |
||
| 1142 |
function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; |
||
| 1143 | |||
| 1144 |
/// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. |
||
| 1145 |
function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; |
||
| 1146 | |||
| 1147 |
/// Asserts that two arrays of `int256` values are equal. |
||
| 1148 |
function assertEq(int256[] calldata left, int256[] calldata right) external pure; |
||
| 1149 | |||
| 1150 |
/// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. |
||
| 1151 |
function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; |
||
| 1152 | |||
| 1153 |
/// Asserts that two `uint256` values are equal. |
||
| 1154 |
function assertEq(uint256 left, uint256 right) external pure; |
||
| 1155 | |||
| 1156 |
/// Asserts that two arrays of `address` values are equal. |
||
| 1157 |
function assertEq(address[] calldata left, address[] calldata right) external pure; |
||
| 1158 | |||
| 1159 |
/// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. |
||
| 1160 |
function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; |
||
| 1161 | |||
| 1162 |
/// Asserts that two arrays of `bytes32` values are equal. |
||
| 1163 |
function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; |
||
| 1164 | |||
| 1165 |
/// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. |
||
| 1166 |
function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; |
||
| 1167 | |||
| 1168 |
/// Asserts that two arrays of `string` values are equal. |
||
| 1169 |
function assertEq(string[] calldata left, string[] calldata right) external pure; |
||
| 1170 | |||
| 1171 |
/// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. |
||
| 1172 |
function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; |
||
| 1173 | |||
| 1174 |
/// Asserts that two arrays of `bytes` values are equal. |
||
| 1175 |
function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; |
||
| 1176 | |||
| 1177 |
/// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. |
||
| 1178 |
function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; |
||
| 1179 | |||
| 1180 |
/// Asserts that two `uint256` values are equal and includes error message into revert string on failure. |
||
| 1181 |
function assertEq(uint256 left, uint256 right, string calldata error) external pure; |
||
| 1182 | |||
| 1183 |
/// Asserts that two `int256` values are equal. |
||
| 1184 |
function assertEq(int256 left, int256 right) external pure; |
||
| 1185 | |||
| 1186 |
/// Asserts that two `int256` values are equal and includes error message into revert string on failure. |
||
| 1187 |
function assertEq(int256 left, int256 right, string calldata error) external pure; |
||
| 1188 | |||
| 1189 |
/// Asserts that two `address` values are equal. |
||
| 1190 |
function assertEq(address left, address right) external pure; |
||
| 1191 | |||
| 1192 |
/// Asserts that two `address` values are equal and includes error message into revert string on failure. |
||
| 1193 |
function assertEq(address left, address right, string calldata error) external pure; |
||
| 1194 | |||
| 1195 |
/// Asserts that two `bytes32` values are equal. |
||
| 1196 |
function assertEq(bytes32 left, bytes32 right) external pure; |
||
| 1197 | |||
| 1198 |
/// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. |
||
| 1199 |
function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; |
||
| 1200 | |||
| 1201 |
/// Asserts that the given condition is false. |
||
| 1202 |
function assertFalse(bool condition) external pure; |
||
| 1203 | |||
| 1204 |
/// Asserts that the given condition is false and includes error message into revert string on failure. |
||
| 1205 |
function assertFalse(bool condition, string calldata error) external pure; |
||
| 1206 | |||
| 1207 |
/// Compares two `uint256` values. Expects first value to be greater than or equal to second. |
||
| 1208 |
/// Formats values with decimals in failure message. |
||
| 1209 |
function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; |
||
| 1210 | |||
| 1211 |
/// Compares two `uint256` values. Expects first value to be greater than or equal to second. |
||
| 1212 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1213 |
function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; |
||
| 1214 | |||
| 1215 |
/// Compares two `int256` values. Expects first value to be greater than or equal to second. |
||
| 1216 |
/// Formats values with decimals in failure message. |
||
| 1217 |
function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; |
||
| 1218 | |||
| 1219 |
/// Compares two `int256` values. Expects first value to be greater than or equal to second. |
||
| 1220 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1221 |
function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; |
||
| 1222 | |||
| 1223 |
/// Compares two `uint256` values. Expects first value to be greater than or equal to second. |
||
| 1224 |
function assertGe(uint256 left, uint256 right) external pure; |
||
| 1225 | |||
| 1226 |
/// Compares two `uint256` values. Expects first value to be greater than or equal to second. |
||
| 1227 |
/// Includes error message into revert string on failure. |
||
| 1228 |
function assertGe(uint256 left, uint256 right, string calldata error) external pure; |
||
| 1229 | |||
| 1230 |
/// Compares two `int256` values. Expects first value to be greater than or equal to second. |
||
| 1231 |
function assertGe(int256 left, int256 right) external pure; |
||
| 1232 | |||
| 1233 |
/// Compares two `int256` values. Expects first value to be greater than or equal to second. |
||
| 1234 |
/// Includes error message into revert string on failure. |
||
| 1235 |
function assertGe(int256 left, int256 right, string calldata error) external pure; |
||
| 1236 | |||
| 1237 |
/// Compares two `uint256` values. Expects first value to be greater than second. |
||
| 1238 |
/// Formats values with decimals in failure message. |
||
| 1239 |
function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; |
||
| 1240 | |||
| 1241 |
/// Compares two `uint256` values. Expects first value to be greater than second. |
||
| 1242 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1243 |
function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; |
||
| 1244 | |||
| 1245 |
/// Compares two `int256` values. Expects first value to be greater than second. |
||
| 1246 |
/// Formats values with decimals in failure message. |
||
| 1247 |
function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; |
||
| 1248 | |||
| 1249 |
/// Compares two `int256` values. Expects first value to be greater than second. |
||
| 1250 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1251 |
function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; |
||
| 1252 | |||
| 1253 |
/// Compares two `uint256` values. Expects first value to be greater than second. |
||
| 1254 |
function assertGt(uint256 left, uint256 right) external pure; |
||
| 1255 | |||
| 1256 |
/// Compares two `uint256` values. Expects first value to be greater than second. |
||
| 1257 |
/// Includes error message into revert string on failure. |
||
| 1258 |
function assertGt(uint256 left, uint256 right, string calldata error) external pure; |
||
| 1259 | |||
| 1260 |
/// Compares two `int256` values. Expects first value to be greater than second. |
||
| 1261 |
function assertGt(int256 left, int256 right) external pure; |
||
| 1262 | |||
| 1263 |
/// Compares two `int256` values. Expects first value to be greater than second. |
||
| 1264 |
/// Includes error message into revert string on failure. |
||
| 1265 |
function assertGt(int256 left, int256 right, string calldata error) external pure; |
||
| 1266 | |||
| 1267 |
/// Compares two `uint256` values. Expects first value to be less than or equal to second. |
||
| 1268 |
/// Formats values with decimals in failure message. |
||
| 1269 |
function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; |
||
| 1270 | |||
| 1271 |
/// Compares two `uint256` values. Expects first value to be less than or equal to second. |
||
| 1272 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1273 |
function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; |
||
| 1274 | |||
| 1275 |
/// Compares two `int256` values. Expects first value to be less than or equal to second. |
||
| 1276 |
/// Formats values with decimals in failure message. |
||
| 1277 |
function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; |
||
| 1278 | |||
| 1279 |
/// Compares two `int256` values. Expects first value to be less than or equal to second. |
||
| 1280 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1281 |
function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; |
||
| 1282 | |||
| 1283 |
/// Compares two `uint256` values. Expects first value to be less than or equal to second. |
||
| 1284 |
function assertLe(uint256 left, uint256 right) external pure; |
||
| 1285 | |||
| 1286 |
/// Compares two `uint256` values. Expects first value to be less than or equal to second. |
||
| 1287 |
/// Includes error message into revert string on failure. |
||
| 1288 |
function assertLe(uint256 left, uint256 right, string calldata error) external pure; |
||
| 1289 | |||
| 1290 |
/// Compares two `int256` values. Expects first value to be less than or equal to second. |
||
| 1291 |
function assertLe(int256 left, int256 right) external pure; |
||
| 1292 | |||
| 1293 |
/// Compares two `int256` values. Expects first value to be less than or equal to second. |
||
| 1294 |
/// Includes error message into revert string on failure. |
||
| 1295 |
function assertLe(int256 left, int256 right, string calldata error) external pure; |
||
| 1296 | |||
| 1297 |
/// Compares two `uint256` values. Expects first value to be less than second. |
||
| 1298 |
/// Formats values with decimals in failure message. |
||
| 1299 |
function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; |
||
| 1300 | |||
| 1301 |
/// Compares two `uint256` values. Expects first value to be less than second. |
||
| 1302 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1303 |
function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; |
||
| 1304 | |||
| 1305 |
/// Compares two `int256` values. Expects first value to be less than second. |
||
| 1306 |
/// Formats values with decimals in failure message. |
||
| 1307 |
function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; |
||
| 1308 | |||
| 1309 |
/// Compares two `int256` values. Expects first value to be less than second. |
||
| 1310 |
/// Formats values with decimals in failure message. Includes error message into revert string on failure. |
||
| 1311 |
function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; |
||
| 1312 | |||
| 1313 |
/// Compares two `uint256` values. Expects first value to be less than second. |
||
| 1314 |
function assertLt(uint256 left, uint256 right) external pure; |
||
| 1315 | |||
| 1316 |
/// Compares two `uint256` values. Expects first value to be less than second. |
||
| 1317 |
/// Includes error message into revert string on failure. |
||
| 1318 |
function assertLt(uint256 left, uint256 right, string calldata error) external pure; |
||
| 1319 | |||
| 1320 |
/// Compares two `int256` values. Expects first value to be less than second. |
||
| 1321 |
function assertLt(int256 left, int256 right) external pure; |
||
| 1322 | |||
| 1323 |
/// Compares two `int256` values. Expects first value to be less than second. |
||
| 1324 |
/// Includes error message into revert string on failure. |
||
| 1325 |
function assertLt(int256 left, int256 right, string calldata error) external pure; |
||
| 1326 | |||
| 1327 |
/// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. |
||
| 1328 |
function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; |
||
| 1329 | |||
| 1330 |
/// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. |
||
| 1331 |
/// Includes error message into revert string on failure. |
||
| 1332 |
function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; |
||
| 1333 | |||
| 1334 |
/// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. |
||
| 1335 |
function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; |
||
| 1336 | |||
| 1337 |
/// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. |
||
| 1338 |
/// Includes error message into revert string on failure. |
||
| 1339 |
function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; |
||
| 1340 | |||
| 1341 |
/// Asserts that two `bool` values are not equal. |
||
| 1342 |
function assertNotEq(bool left, bool right) external pure; |
||
| 1343 | |||
| 1344 |
/// Asserts that two `bool` values are not equal and includes error message into revert string on failure. |
||
| 1345 |
function assertNotEq(bool left, bool right, string calldata error) external pure; |
||
| 1346 | |||
| 1347 |
/// Asserts that two `string` values are not equal. |
||
| 1348 |
function assertNotEq(string calldata left, string calldata right) external pure; |
||
| 1349 | |||
| 1350 |
/// Asserts that two `string` values are not equal and includes error message into revert string on failure. |
||
| 1351 |
function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; |
||
| 1352 | |||
| 1353 |
/// Asserts that two `bytes` values are not equal. |
||
| 1354 |
function assertNotEq(bytes calldata left, bytes calldata right) external pure; |
||
| 1355 | |||
| 1356 |
/// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. |
||
| 1357 |
function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; |
||
| 1358 | |||
| 1359 |
/// Asserts that two arrays of `bool` values are not equal. |
||
| 1360 |
function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; |
||
| 1361 | |||
| 1362 |
/// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. |
||
| 1363 |
function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; |
||
| 1364 | |||
| 1365 |
/// Asserts that two arrays of `uint256` values are not equal. |
||
| 1366 |
function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; |
||
| 1367 | |||
| 1368 |
/// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. |
||
| 1369 |
function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; |
||
| 1370 | |||
| 1371 |
/// Asserts that two arrays of `int256` values are not equal. |
||
| 1372 |
function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; |
||
| 1373 | |||
| 1374 |
/// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. |
||
| 1375 |
function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; |
||
| 1376 | |||
| 1377 |
/// Asserts that two `uint256` values are not equal. |
||
| 1378 |
function assertNotEq(uint256 left, uint256 right) external pure; |
||
| 1379 | |||
| 1380 |
/// Asserts that two arrays of `address` values are not equal. |
||
| 1381 |
function assertNotEq(address[] calldata left, address[] calldata right) external pure; |
||
| 1382 | |||
| 1383 |
/// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. |
||
| 1384 |
function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; |
||
| 1385 | |||
| 1386 |
/// Asserts that two arrays of `bytes32` values are not equal. |
||
| 1387 |
function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; |
||
| 1388 | |||
| 1389 |
/// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. |
||
| 1390 |
function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; |
||
| 1391 | |||
| 1392 |
/// Asserts that two arrays of `string` values are not equal. |
||
| 1393 |
function assertNotEq(string[] calldata left, string[] calldata right) external pure; |
||
| 1394 | |||
| 1395 |
/// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. |
||
| 1396 |
function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; |
||
| 1397 | |||
| 1398 |
/// Asserts that two arrays of `bytes` values are not equal. |
||
| 1399 |
function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; |
||
| 1400 | |||
| 1401 |
/// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. |
||
| 1402 |
function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; |
||
| 1403 | |||
| 1404 |
/// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. |
||
| 1405 |
function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; |
||
| 1406 | |||
| 1407 |
/// Asserts that two `int256` values are not equal. |
||
| 1408 |
function assertNotEq(int256 left, int256 right) external pure; |
||
| 1409 | |||
| 1410 |
/// Asserts that two `int256` values are not equal and includes error message into revert string on failure. |
||
| 1411 |
function assertNotEq(int256 left, int256 right, string calldata error) external pure; |
||
| 1412 | |||
| 1413 |
/// Asserts that two `address` values are not equal. |
||
| 1414 |
function assertNotEq(address left, address right) external pure; |
||
| 1415 | |||
| 1416 |
/// Asserts that two `address` values are not equal and includes error message into revert string on failure. |
||
| 1417 |
function assertNotEq(address left, address right, string calldata error) external pure; |
||
| 1418 | |||
| 1419 |
/// Asserts that two `bytes32` values are not equal. |
||
| 1420 |
function assertNotEq(bytes32 left, bytes32 right) external pure; |
||
| 1421 | |||
| 1422 |
/// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. |
||
| 1423 |
function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; |
||
| 1424 | |||
| 1425 |
/// Asserts that the given condition is true. |
||
| 1426 |
function assertTrue(bool condition) external pure; |
||
| 1427 | |||
| 1428 |
/// Asserts that the given condition is true and includes error message into revert string on failure. |
||
| 1429 |
function assertTrue(bool condition, string calldata error) external pure; |
||
| 1430 | |||
| 1431 |
/// If the condition is false, discard this run's fuzz inputs and generate new ones. |
||
| 1432 |
function assume(bool condition) external pure; |
||
| 1433 | |||
| 1434 |
/// Writes a breakpoint to jump to in the debugger. |
||
| 1435 |
function breakpoint(string calldata char) external; |
||
| 1436 | |||
| 1437 |
/// Writes a conditional breakpoint to jump to in the debugger. |
||
| 1438 |
function breakpoint(string calldata char, bool value) external; |
||
| 1439 | |||
| 1440 |
/// Returns the Foundry version. |
||
| 1441 |
/// Format: <cargo_version>+<git_sha>+<build_timestamp> |
||
| 1442 |
/// Sample output: 0.2.0+faa94c384+202407110019 |
||
| 1443 |
/// Note: Build timestamps may vary slightly across platforms due to separate CI jobs. |
||
| 1444 |
/// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000) |
||
| 1445 |
/// to compare timestamps while ignoring minor time differences. |
||
| 1446 |
function getFoundryVersion() external view returns (string memory version); |
||
| 1447 | |||
| 1448 |
/// Returns the RPC url for the given alias. |
||
| 1449 |
function rpcUrl(string calldata rpcAlias) external view returns (string memory json); |
||
| 1450 | |||
| 1451 |
/// Returns all rpc urls and their aliases as structs. |
||
| 1452 |
function rpcUrlStructs() external view returns (Rpc[] memory urls); |
||
| 1453 | |||
| 1454 |
/// Returns all rpc urls and their aliases `[alias, url][]`. |
||
| 1455 |
function rpcUrls() external view returns (string[2][] memory urls); |
||
| 1456 | |||
| 1457 |
/// Suspends execution of the main thread for `duration` milliseconds. |
||
| 1458 |
function sleep(uint256 duration) external; |
||
| 1459 | |||
| 1460 |
// ======== Toml ======== |
||
| 1461 | |||
| 1462 |
/// Checks if `key` exists in a TOML table. |
||
| 1463 |
function keyExistsToml(string calldata toml, string calldata key) external view returns (bool); |
||
| 1464 | |||
| 1465 |
/// Parses a string of TOML data at `key` and coerces it to `address`. |
||
| 1466 |
function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); |
||
| 1467 | |||
| 1468 |
/// Parses a string of TOML data at `key` and coerces it to `address[]`. |
||
| 1469 |
function parseTomlAddressArray(string calldata toml, string calldata key) |
||
| 1470 |
external |
||
| 1471 |
pure |
||
| 1472 |
returns (address[] memory); |
||
| 1473 | |||
| 1474 |
/// Parses a string of TOML data at `key` and coerces it to `bool`. |
||
| 1475 |
function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); |
||
| 1476 | |||
| 1477 |
/// Parses a string of TOML data at `key` and coerces it to `bool[]`. |
||
| 1478 |
function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory); |
||
| 1479 | |||
| 1480 |
/// Parses a string of TOML data at `key` and coerces it to `bytes`. |
||
| 1481 |
function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory); |
||
| 1482 | |||
| 1483 |
/// Parses a string of TOML data at `key` and coerces it to `bytes32`. |
||
| 1484 |
function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); |
||
| 1485 | |||
| 1486 |
/// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. |
||
| 1487 |
function parseTomlBytes32Array(string calldata toml, string calldata key) |
||
| 1488 |
external |
||
| 1489 |
pure |
||
| 1490 |
returns (bytes32[] memory); |
||
| 1491 | |||
| 1492 |
/// Parses a string of TOML data at `key` and coerces it to `bytes[]`. |
||
| 1493 |
function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); |
||
| 1494 | |||
| 1495 |
/// Parses a string of TOML data at `key` and coerces it to `int256`. |
||
| 1496 |
function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256); |
||
| 1497 | |||
| 1498 |
/// Parses a string of TOML data at `key` and coerces it to `int256[]`. |
||
| 1499 |
function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory); |
||
| 1500 | |||
| 1501 |
/// Returns an array of all the keys in a TOML table. |
||
| 1502 |
function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys); |
||
| 1503 | |||
| 1504 |
/// Parses a string of TOML data at `key` and coerces it to `string`. |
||
| 1505 |
function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory); |
||
| 1506 | |||
| 1507 |
/// Parses a string of TOML data at `key` and coerces it to `string[]`. |
||
| 1508 |
function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); |
||
| 1509 | |||
| 1510 |
/// Parses a string of TOML data at `key` and coerces it to `uint256`. |
||
| 1511 |
function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); |
||
| 1512 | |||
| 1513 |
/// Parses a string of TOML data at `key` and coerces it to `uint256[]`. |
||
| 1514 |
function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory); |
||
| 1515 | |||
| 1516 |
/// ABI-encodes a TOML table. |
||
| 1517 |
function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData); |
||
| 1518 | |||
| 1519 |
/// ABI-encodes a TOML table at `key`. |
||
| 1520 |
function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData); |
||
| 1521 | |||
| 1522 |
/// Takes serialized JSON, converts to TOML and write a serialized TOML to a file. |
||
| 1523 |
function writeToml(string calldata json, string calldata path) external; |
||
| 1524 | |||
| 1525 |
/// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.> |
||
| 1526 |
/// This is useful to replace a specific value of a TOML file, without having to parse the entire thing. |
||
| 1527 |
function writeToml(string calldata json, string calldata path, string calldata valueKey) external; |
||
| 1528 | |||
| 1529 |
// ======== Utilities ======== |
||
| 1530 | |||
| 1531 |
/// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. |
||
| 1532 |
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) |
||
| 1533 |
external |
||
| 1534 |
pure |
||
| 1535 |
returns (address); |
||
| 1536 | |||
| 1537 |
/// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. |
||
| 1538 |
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); |
||
| 1539 | |||
| 1540 |
/// Compute the address a contract will be deployed at for a given deployer address and nonce. |
||
| 1541 |
function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); |
||
| 1542 | |||
| 1543 |
/// Returns ENS namehash for provided string. |
||
| 1544 |
function ensNamehash(string calldata name) external pure returns (bytes32); |
||
| 1545 | |||
| 1546 |
/// Gets the label for the specified address. |
||
| 1547 |
function getLabel(address account) external view returns (string memory currentLabel); |
||
| 1548 | |||
| 1549 |
/// Labels an address in call traces. |
||
| 1550 |
function label(address account, string calldata newLabel) external; |
||
| 1551 | |||
| 1552 |
/// Returns a random `address`. |
||
| 1553 |
function randomAddress() external returns (address); |
||
| 1554 | |||
| 1555 |
/// Returns a random uint256 value. |
||
| 1556 |
function randomUint() external returns (uint256); |
||
| 1557 | |||
| 1558 |
/// Returns random uin256 value between the provided range (=min..=max). |
||
| 1559 |
function randomUint(uint256 min, uint256 max) external returns (uint256); |
||
| 1560 | |||
| 1561 |
/// Encodes a `bytes` value to a base64url string. |
||
| 1562 |
function toBase64URL(bytes calldata data) external pure returns (string memory); |
||
| 1563 | |||
| 1564 |
/// Encodes a `string` value to a base64url string. |
||
| 1565 |
function toBase64URL(string calldata data) external pure returns (string memory); |
||
| 1566 | |||
| 1567 |
/// Encodes a `bytes` value to a base64 string. |
||
| 1568 |
function toBase64(bytes calldata data) external pure returns (string memory); |
||
| 1569 | |||
| 1570 |
/// Encodes a `string` value to a base64 string. |
||
| 1571 |
function toBase64(string calldata data) external pure returns (string memory); |
||
| 1572 |
} |
||
| 1573 | |||
| 1574 |
/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used |
||
| 1575 |
/// in tests, but it is not recommended to use these cheats in scripts. |
||
| 1576 |
interface Vm is VmSafe {
|
||
| 1577 |
// ======== EVM ======== |
||
| 1578 | |||
| 1579 |
/// Returns the identifier of the currently active fork. Reverts if no fork is currently active. |
||
| 1580 |
function activeFork() external view returns (uint256 forkId); |
||
| 1581 | |||
| 1582 |
/// In forking mode, explicitly grant the given address cheatcode access. |
||
| 1583 |
function allowCheatcodes(address account) external; |
||
| 1584 | |||
| 1585 |
/// Sets `block.blobbasefee` |
||
| 1586 |
function blobBaseFee(uint256 newBlobBaseFee) external; |
||
| 1587 | |||
| 1588 |
/// Sets the blobhashes in the transaction. |
||
| 1589 |
/// Not available on EVM versions before Cancun. |
||
| 1590 |
/// If used on unsupported EVM versions it will revert. |
||
| 1591 |
function blobhashes(bytes32[] calldata hashes) external; |
||
| 1592 | |||
| 1593 |
/// Sets `block.chainid`. |
||
| 1594 |
function chainId(uint256 newChainId) external; |
||
| 1595 | |||
| 1596 |
/// Clears all mocked calls. |
||
| 1597 |
function clearMockedCalls() external; |
||
| 1598 | |||
| 1599 |
/// Sets `block.coinbase`. |
||
| 1600 |
function coinbase(address newCoinbase) external; |
||
| 1601 | |||
| 1602 |
/// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork. |
||
| 1603 |
function createFork(string calldata urlOrAlias) external returns (uint256 forkId); |
||
| 1604 | |||
| 1605 |
/// Creates a new fork with the given endpoint and block and returns the identifier of the fork. |
||
| 1606 |
function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); |
||
| 1607 | |||
| 1608 |
/// Creates a new fork with the given endpoint and at the block the given transaction was mined in, |
||
| 1609 |
/// replays all transaction mined in the block before the transaction, and returns the identifier of the fork. |
||
| 1610 |
function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); |
||
| 1611 | |||
| 1612 |
/// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork. |
||
| 1613 |
function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId); |
||
| 1614 | |||
| 1615 |
/// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork. |
||
| 1616 |
function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); |
||
| 1617 | |||
| 1618 |
/// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, |
||
| 1619 |
/// replays all transaction mined in the block before the transaction, returns the identifier of the fork. |
||
| 1620 |
function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); |
||
| 1621 | |||
| 1622 |
/// Sets an address' balance. |
||
| 1623 |
function deal(address account, uint256 newBalance) external; |
||
| 1624 | |||
| 1625 |
/// Removes the snapshot with the given ID created by `snapshot`. |
||
| 1626 |
/// Takes the snapshot ID to delete. |
||
| 1627 |
/// Returns `true` if the snapshot was successfully deleted. |
||
| 1628 |
/// Returns `false` if the snapshot does not exist. |
||
| 1629 |
function deleteSnapshot(uint256 snapshotId) external returns (bool success); |
||
| 1630 | |||
| 1631 |
/// Removes _all_ snapshots previously created by `snapshot`. |
||
| 1632 |
function deleteSnapshots() external; |
||
| 1633 | |||
| 1634 |
/// Sets `block.difficulty`. |
||
| 1635 |
/// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. |
||
| 1636 |
/// Reverts if used on unsupported EVM versions. |
||
| 1637 |
function difficulty(uint256 newDifficulty) external; |
||
| 1638 | |||
| 1639 |
/// Dump a genesis JSON file's `allocs` to disk. |
||
| 1640 |
function dumpState(string calldata pathToStateJson) external; |
||
| 1641 | |||
| 1642 |
/// Sets an address' code. |
||
| 1643 |
function etch(address target, bytes calldata newRuntimeBytecode) external; |
||
| 1644 | |||
| 1645 |
/// Sets `block.basefee`. |
||
| 1646 |
function fee(uint256 newBasefee) external; |
||
| 1647 | |||
| 1648 |
/// Gets the blockhashes from the current transaction. |
||
| 1649 |
/// Not available on EVM versions before Cancun. |
||
| 1650 |
/// If used on unsupported EVM versions it will revert. |
||
| 1651 |
function getBlobhashes() external view returns (bytes32[] memory hashes); |
||
| 1652 | |||
| 1653 |
/// Returns true if the account is marked as persistent. |
||
| 1654 |
function isPersistent(address account) external view returns (bool persistent); |
||
| 1655 | |||
| 1656 |
/// Load a genesis JSON file's `allocs` into the in-memory revm state. |
||
| 1657 |
function loadAllocs(string calldata pathToAllocsJson) external; |
||
| 1658 | |||
| 1659 |
/// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup |
||
| 1660 |
/// Meaning, changes made to the state of this account will be kept when switching forks. |
||
| 1661 |
function makePersistent(address account) external; |
||
| 1662 | |||
| 1663 |
/// See `makePersistent(address)`. |
||
| 1664 |
function makePersistent(address account0, address account1) external; |
||
| 1665 | |||
| 1666 |
/// See `makePersistent(address)`. |
||
| 1667 |
function makePersistent(address account0, address account1, address account2) external; |
||
| 1668 | |||
| 1669 |
/// See `makePersistent(address)`. |
||
| 1670 |
function makePersistent(address[] calldata accounts) external; |
||
| 1671 | |||
| 1672 |
/// Reverts a call to an address with specified revert data. |
||
| 1673 |
function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; |
||
| 1674 | |||
| 1675 |
/// Reverts a call to an address with a specific `msg.value`, with specified revert data. |
||
| 1676 |
function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) |
||
| 1677 |
external; |
||
| 1678 | |||
| 1679 |
/// Mocks a call to an address, returning specified data. |
||
| 1680 |
/// Calldata can either be strict or a partial match, e.g. if you only |
||
| 1681 |
/// pass a Solidity selector to the expected calldata, then the entire Solidity |
||
| 1682 |
/// function will be mocked. |
||
| 1683 |
function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; |
||
| 1684 | |||
| 1685 |
/// Mocks a call to an address with a specific `msg.value`, returning specified data. |
||
| 1686 |
/// Calldata match takes precedence over `msg.value` in case of ambiguity. |
||
| 1687 |
function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; |
||
| 1688 | |||
| 1689 |
/// Sets the *next* call's `msg.sender` to be the input address. |
||
| 1690 |
function prank(address msgSender) external; |
||
| 1691 | |||
| 1692 |
/// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. |
||
| 1693 |
function prank(address msgSender, address txOrigin) external; |
||
| 1694 | |||
| 1695 |
/// Sets `block.prevrandao`. |
||
| 1696 |
/// Not available on EVM versions before Paris. Use `difficulty` instead. |
||
| 1697 |
/// If used on unsupported EVM versions it will revert. |
||
| 1698 |
function prevrandao(bytes32 newPrevrandao) external; |
||
| 1699 | |||
| 1700 |
/// Sets `block.prevrandao`. |
||
| 1701 |
/// Not available on EVM versions before Paris. Use `difficulty` instead. |
||
| 1702 |
/// If used on unsupported EVM versions it will revert. |
||
| 1703 |
function prevrandao(uint256 newPrevrandao) external; |
||
| 1704 | |||
| 1705 |
/// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification. |
||
| 1706 |
function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin); |
||
| 1707 | |||
| 1708 |
/// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts. |
||
| 1709 |
function resetNonce(address account) external; |
||
| 1710 | |||
| 1711 |
/// Revert the state of the EVM to a previous snapshot |
||
| 1712 |
/// Takes the snapshot ID to revert to. |
||
| 1713 |
/// Returns `true` if the snapshot was successfully reverted. |
||
| 1714 |
/// Returns `false` if the snapshot does not exist. |
||
| 1715 |
/// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. |
||
| 1716 |
function revertTo(uint256 snapshotId) external returns (bool success); |
||
| 1717 | |||
| 1718 |
/// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots |
||
| 1719 |
/// Takes the snapshot ID to revert to. |
||
| 1720 |
/// Returns `true` if the snapshot was successfully reverted and deleted. |
||
| 1721 |
/// Returns `false` if the snapshot does not exist. |
||
| 1722 |
function revertToAndDelete(uint256 snapshotId) external returns (bool success); |
||
| 1723 | |||
| 1724 |
/// Revokes persistent status from the address, previously added via `makePersistent`. |
||
| 1725 |
function revokePersistent(address account) external; |
||
| 1726 | |||
| 1727 |
/// See `revokePersistent(address)`. |
||
| 1728 |
function revokePersistent(address[] calldata accounts) external; |
||
| 1729 | |||
| 1730 |
/// Sets `block.height`. |
||
| 1731 |
function roll(uint256 newHeight) external; |
||
| 1732 | |||
| 1733 |
/// Updates the currently active fork to given block number |
||
| 1734 |
/// This is similar to `roll` but for the currently active fork. |
||
| 1735 |
function rollFork(uint256 blockNumber) external; |
||
| 1736 | |||
| 1737 |
/// Updates the currently active fork to given transaction. This will `rollFork` with the number |
||
| 1738 |
/// of the block the transaction was mined in and replays all transaction mined before it in the block. |
||
| 1739 |
function rollFork(bytes32 txHash) external; |
||
| 1740 | |||
| 1741 |
/// Updates the given fork to given block number. |
||
| 1742 |
function rollFork(uint256 forkId, uint256 blockNumber) external; |
||
| 1743 | |||
| 1744 |
/// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block. |
||
| 1745 |
function rollFork(uint256 forkId, bytes32 txHash) external; |
||
| 1746 | |||
| 1747 |
/// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. |
||
| 1748 |
function selectFork(uint256 forkId) external; |
||
| 1749 | |||
| 1750 |
/// Set blockhash for the current block. |
||
| 1751 |
/// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. |
||
| 1752 |
function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; |
||
| 1753 | |||
| 1754 |
/// Sets the nonce of an account. Must be higher than the current nonce of the account. |
||
| 1755 |
function setNonce(address account, uint64 newNonce) external; |
||
| 1756 | |||
| 1757 |
/// Sets the nonce of an account to an arbitrary value. |
||
| 1758 |
function setNonceUnsafe(address account, uint64 newNonce) external; |
||
| 1759 | |||
| 1760 |
/// Snapshot the current state of the evm. |
||
| 1761 |
/// Returns the ID of the snapshot that was created. |
||
| 1762 |
/// To revert a snapshot use `revertTo`. |
||
| 1763 |
function snapshot() external returns (uint256 snapshotId); |
||
| 1764 | |||
| 1765 |
/// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. |
||
| 1766 |
function startPrank(address msgSender) external; |
||
| 1767 | |||
| 1768 |
/// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. |
||
| 1769 |
function startPrank(address msgSender, address txOrigin) external; |
||
| 1770 | |||
| 1771 |
/// Resets subsequent calls' `msg.sender` to be `address(this)`. |
||
| 1772 |
function stopPrank() external; |
||
| 1773 | |||
| 1774 |
/// Stores a value to an address' storage slot. |
||
| 1775 |
function store(address target, bytes32 slot, bytes32 value) external; |
||
| 1776 | |||
| 1777 |
/// Fetches the given transaction from the active fork and executes it on the current state. |
||
| 1778 |
function transact(bytes32 txHash) external; |
||
| 1779 | |||
| 1780 |
/// Fetches the given transaction from the given fork and executes it on the current state. |
||
| 1781 |
function transact(uint256 forkId, bytes32 txHash) external; |
||
| 1782 | |||
| 1783 |
/// Sets `tx.gasprice`. |
||
| 1784 |
function txGasPrice(uint256 newGasPrice) external; |
||
| 1785 | |||
| 1786 |
/// Sets `block.timestamp`. |
||
| 1787 |
function warp(uint256 newTimestamp) external; |
||
| 1788 | |||
| 1789 |
// ======== Testing ======== |
||
| 1790 | |||
| 1791 |
/// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. |
||
| 1792 |
function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; |
||
| 1793 | |||
| 1794 |
/// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. |
||
| 1795 |
function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) |
||
| 1796 |
external; |
||
| 1797 | |||
| 1798 |
/// Expects a call to an address with the specified calldata. |
||
| 1799 |
/// Calldata can either be a strict or a partial match. |
||
| 1800 |
function expectCall(address callee, bytes calldata data) external; |
||
| 1801 | |||
| 1802 |
/// Expects given number of calls to an address with the specified calldata. |
||
| 1803 |
function expectCall(address callee, bytes calldata data, uint64 count) external; |
||
| 1804 | |||
| 1805 |
/// Expects a call to an address with the specified `msg.value` and calldata. |
||
| 1806 |
function expectCall(address callee, uint256 msgValue, bytes calldata data) external; |
||
| 1807 | |||
| 1808 |
/// Expects given number of calls to an address with the specified `msg.value` and calldata. |
||
| 1809 |
function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external; |
||
| 1810 | |||
| 1811 |
/// Expect a call to an address with the specified `msg.value`, gas, and calldata. |
||
| 1812 |
function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external; |
||
| 1813 | |||
| 1814 |
/// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. |
||
| 1815 |
function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; |
||
| 1816 | |||
| 1817 |
/// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). |
||
| 1818 |
/// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if |
||
| 1819 |
/// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). |
||
| 1820 |
function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) |
||
| 1821 |
external; |
||
| 1822 | |||
| 1823 |
/// Same as the previous method, but also checks supplied address against emitting contract. |
||
| 1824 |
function expectEmitAnonymous( |
||
| 1825 |
bool checkTopic0, |
||
| 1826 |
bool checkTopic1, |
||
| 1827 |
bool checkTopic2, |
||
| 1828 |
bool checkTopic3, |
||
| 1829 |
bool checkData, |
||
| 1830 |
address emitter |
||
| 1831 |
) external; |
||
| 1832 | |||
| 1833 |
/// Prepare an expected anonymous log with all topic and data checks enabled. |
||
| 1834 |
/// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if |
||
| 1835 |
/// logs were emitted in the expected order with the expected topics and data. |
||
| 1836 |
function expectEmitAnonymous() external; |
||
| 1837 | |||
| 1838 |
/// Same as the previous method, but also checks supplied address against emitting contract. |
||
| 1839 |
function expectEmitAnonymous(address emitter) external; |
||
| 1840 | |||
| 1841 |
/// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). |
||
| 1842 |
/// Call this function, then emit an event, then call a function. Internally after the call, we check if |
||
| 1843 |
/// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). |
||
| 1844 |
function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; |
||
| 1845 | |||
| 1846 |
/// Same as the previous method, but also checks supplied address against emitting contract. |
||
| 1847 |
function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) |
||
| 1848 |
external; |
||
| 1849 | |||
| 1850 |
/// Prepare an expected log with all topic and data checks enabled. |
||
| 1851 |
/// Call this function, then emit an event, then call a function. Internally after the call, we check if |
||
| 1852 |
/// logs were emitted in the expected order with the expected topics and data. |
||
| 1853 |
function expectEmit() external; |
||
| 1854 | |||
| 1855 |
/// Same as the previous method, but also checks supplied address against emitting contract. |
||
| 1856 |
function expectEmit(address emitter) external; |
||
| 1857 | |||
| 1858 |
/// Expects an error on next call with any revert data. |
||
| 1859 |
function expectRevert() external; |
||
| 1860 | |||
| 1861 |
/// Expects an error on next call that starts with the revert data. |
||
| 1862 |
function expectRevert(bytes4 revertData) external; |
||
| 1863 | |||
| 1864 |
/// Expects an error on next call that exactly matches the revert data. |
||
| 1865 |
function expectRevert(bytes calldata revertData) external; |
||
| 1866 | |||
| 1867 |
/// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other |
||
| 1868 |
/// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. |
||
| 1869 |
function expectSafeMemory(uint64 min, uint64 max) external; |
||
| 1870 | |||
| 1871 |
/// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext. |
||
| 1872 |
/// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges |
||
| 1873 |
/// to the set. |
||
| 1874 |
function expectSafeMemoryCall(uint64 min, uint64 max) external; |
||
| 1875 | |||
| 1876 |
/// Marks a test as skipped. Must be called at the top of the test. |
||
| 1877 |
function skip(bool skipTest) external; |
||
| 1878 | |||
| 1879 |
/// Stops all safe memory expectation in the current subcontext. |
||
| 1880 |
function stopExpectSafeMemory() external; |
||
| 1881 |
} |
||
| 1882 |
| Lines covered: | 0 / 10 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.4.22 <0.9.0; |
||
| 3 | |||
| 4 |
library console {
|
||
| 5 |
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); |
||
| 6 | |||
| 7 |
function _castLogPayloadViewToPure( |
||
| 8 |
function(bytes memory) internal view fnIn |
||
| 9 |
) internal pure returns (function(bytes memory) internal pure fnOut) {
|
||
| 10 |
assembly {
|
||
| 11 |
fnOut := fnIn |
||
| 12 |
} |
||
| 13 |
} |
||
| 14 | |||
| 15 |
function _sendLogPayload(bytes memory payload) internal pure {
|
||
| 16 |
_castLogPayloadViewToPure(_sendLogPayloadView)(payload); |
||
| 17 |
} |
||
| 18 | |||
| 19 |
function _sendLogPayloadView(bytes memory payload) private view {
|
||
| 20 |
uint256 payloadLength = payload.length; |
||
| 21 |
address consoleAddress = CONSOLE_ADDRESS; |
||
| 22 |
/// @solidity memory-safe-assembly |
||
| 23 |
assembly {
|
||
| 24 |
let payloadStart := add(payload, 32) |
||
| 25 |
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) |
||
| 26 |
} |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function log() internal pure {
|
||
| 30 |
_sendLogPayload(abi.encodeWithSignature("log()"));
|
||
| 31 |
} |
||
| 32 | |||
| 33 |
function logInt(int p0) internal pure {
|
||
| 34 |
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
|
||
| 35 |
} |
||
| 36 | |||
| 37 |
function logUint(uint p0) internal pure {
|
||
| 38 |
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
|
||
| 39 |
} |
||
| 40 | |||
| 41 |
function logString(string memory p0) internal pure {
|
||
| 42 |
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
|
||
| 43 |
} |
||
| 44 | |||
| 45 |
function logBool(bool p0) internal pure {
|
||
| 46 |
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
|
||
| 47 |
} |
||
| 48 | |||
| 49 |
function logAddress(address p0) internal pure {
|
||
| 50 |
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
|
||
| 51 |
} |
||
| 52 | |||
| 53 |
function logBytes(bytes memory p0) internal pure {
|
||
| 54 |
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
|
||
| 55 |
} |
||
| 56 | |||
| 57 |
function logBytes1(bytes1 p0) internal pure {
|
||
| 58 |
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
|
||
| 59 |
} |
||
| 60 | |||
| 61 |
function logBytes2(bytes2 p0) internal pure {
|
||
| 62 |
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
|
||
| 63 |
} |
||
| 64 | |||
| 65 |
function logBytes3(bytes3 p0) internal pure {
|
||
| 66 |
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
|
||
| 67 |
} |
||
| 68 | |||
| 69 |
function logBytes4(bytes4 p0) internal pure {
|
||
| 70 |
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
|
||
| 71 |
} |
||
| 72 | |||
| 73 |
function logBytes5(bytes5 p0) internal pure {
|
||
| 74 |
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
|
||
| 75 |
} |
||
| 76 | |||
| 77 |
function logBytes6(bytes6 p0) internal pure {
|
||
| 78 |
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
|
||
| 79 |
} |
||
| 80 | |||
| 81 |
function logBytes7(bytes7 p0) internal pure {
|
||
| 82 |
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
|
||
| 83 |
} |
||
| 84 | |||
| 85 |
function logBytes8(bytes8 p0) internal pure {
|
||
| 86 |
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
|
||
| 87 |
} |
||
| 88 | |||
| 89 |
function logBytes9(bytes9 p0) internal pure {
|
||
| 90 |
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
|
||
| 91 |
} |
||
| 92 | |||
| 93 |
function logBytes10(bytes10 p0) internal pure {
|
||
| 94 |
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
|
||
| 95 |
} |
||
| 96 | |||
| 97 |
function logBytes11(bytes11 p0) internal pure {
|
||
| 98 |
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
|
||
| 99 |
} |
||
| 100 | |||
| 101 |
function logBytes12(bytes12 p0) internal pure {
|
||
| 102 |
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
|
||
| 103 |
} |
||
| 104 | |||
| 105 |
function logBytes13(bytes13 p0) internal pure {
|
||
| 106 |
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
|
||
| 107 |
} |
||
| 108 | |||
| 109 |
function logBytes14(bytes14 p0) internal pure {
|
||
| 110 |
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
|
||
| 111 |
} |
||
| 112 | |||
| 113 |
function logBytes15(bytes15 p0) internal pure {
|
||
| 114 |
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
|
||
| 115 |
} |
||
| 116 | |||
| 117 |
function logBytes16(bytes16 p0) internal pure {
|
||
| 118 |
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
|
||
| 119 |
} |
||
| 120 | |||
| 121 |
function logBytes17(bytes17 p0) internal pure {
|
||
| 122 |
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
|
||
| 123 |
} |
||
| 124 | |||
| 125 |
function logBytes18(bytes18 p0) internal pure {
|
||
| 126 |
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
|
||
| 127 |
} |
||
| 128 | |||
| 129 |
function logBytes19(bytes19 p0) internal pure {
|
||
| 130 |
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
|
||
| 131 |
} |
||
| 132 | |||
| 133 |
function logBytes20(bytes20 p0) internal pure {
|
||
| 134 |
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
|
||
| 135 |
} |
||
| 136 | |||
| 137 |
function logBytes21(bytes21 p0) internal pure {
|
||
| 138 |
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
|
||
| 139 |
} |
||
| 140 | |||
| 141 |
function logBytes22(bytes22 p0) internal pure {
|
||
| 142 |
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
|
||
| 143 |
} |
||
| 144 | |||
| 145 |
function logBytes23(bytes23 p0) internal pure {
|
||
| 146 |
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
|
||
| 147 |
} |
||
| 148 | |||
| 149 |
function logBytes24(bytes24 p0) internal pure {
|
||
| 150 |
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
|
||
| 151 |
} |
||
| 152 | |||
| 153 |
function logBytes25(bytes25 p0) internal pure {
|
||
| 154 |
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
|
||
| 155 |
} |
||
| 156 | |||
| 157 |
function logBytes26(bytes26 p0) internal pure {
|
||
| 158 |
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
|
||
| 159 |
} |
||
| 160 | |||
| 161 |
function logBytes27(bytes27 p0) internal pure {
|
||
| 162 |
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
|
||
| 163 |
} |
||
| 164 | |||
| 165 |
function logBytes28(bytes28 p0) internal pure {
|
||
| 166 |
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
|
||
| 167 |
} |
||
| 168 | |||
| 169 |
function logBytes29(bytes29 p0) internal pure {
|
||
| 170 |
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
|
||
| 171 |
} |
||
| 172 | |||
| 173 |
function logBytes30(bytes30 p0) internal pure {
|
||
| 174 |
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
|
||
| 175 |
} |
||
| 176 | |||
| 177 |
function logBytes31(bytes31 p0) internal pure {
|
||
| 178 |
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
|
||
| 179 |
} |
||
| 180 | |||
| 181 |
function logBytes32(bytes32 p0) internal pure {
|
||
| 182 |
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
|
||
| 183 |
} |
||
| 184 | |||
| 185 |
function log(uint p0) internal pure {
|
||
| 186 |
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
|
||
| 187 |
} |
||
| 188 | |||
| 189 |
function log(int p0) internal pure {
|
||
| 190 |
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
|
||
| 191 |
} |
||
| 192 | |||
| 193 |
function log(string memory p0) internal pure {
|
||
| 194 |
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
|
||
| 195 |
} |
||
| 196 | |||
| 197 |
function log(bool p0) internal pure {
|
||
| 198 |
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
|
||
| 199 |
} |
||
| 200 | |||
| 201 |
function log(address p0) internal pure {
|
||
| 202 |
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
|
||
| 203 |
} |
||
| 204 | |||
| 205 |
function log(uint p0, uint p1) internal pure {
|
||
| 206 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
|
||
| 207 |
} |
||
| 208 | |||
| 209 |
function log(uint p0, string memory p1) internal pure {
|
||
| 210 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
|
||
| 211 |
} |
||
| 212 | |||
| 213 |
function log(uint p0, bool p1) internal pure {
|
||
| 214 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
|
||
| 215 |
} |
||
| 216 | |||
| 217 |
function log(uint p0, address p1) internal pure {
|
||
| 218 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
|
||
| 219 |
} |
||
| 220 | |||
| 221 |
function log(string memory p0, uint p1) internal pure {
|
||
| 222 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
|
||
| 223 |
} |
||
| 224 | |||
| 225 |
function log(string memory p0, int p1) internal pure {
|
||
| 226 |
_sendLogPayload(abi.encodeWithSignature("log(string,int)", p0, p1));
|
||
| 227 |
} |
||
| 228 | |||
| 229 |
function log(string memory p0, string memory p1) internal pure {
|
||
| 230 |
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
|
||
| 231 |
} |
||
| 232 | |||
| 233 |
function log(string memory p0, bool p1) internal pure {
|
||
| 234 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
|
||
| 235 |
} |
||
| 236 | |||
| 237 |
function log(string memory p0, address p1) internal pure {
|
||
| 238 |
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
|
||
| 239 |
} |
||
| 240 | |||
| 241 |
function log(bool p0, uint p1) internal pure {
|
||
| 242 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
|
||
| 243 |
} |
||
| 244 | |||
| 245 |
function log(bool p0, string memory p1) internal pure {
|
||
| 246 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
|
||
| 247 |
} |
||
| 248 | |||
| 249 |
function log(bool p0, bool p1) internal pure {
|
||
| 250 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
|
||
| 251 |
} |
||
| 252 | |||
| 253 |
function log(bool p0, address p1) internal pure {
|
||
| 254 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
|
||
| 255 |
} |
||
| 256 | |||
| 257 |
function log(address p0, uint p1) internal pure {
|
||
| 258 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
|
||
| 259 |
} |
||
| 260 | |||
| 261 |
function log(address p0, string memory p1) internal pure {
|
||
| 262 |
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
|
||
| 263 |
} |
||
| 264 | |||
| 265 |
function log(address p0, bool p1) internal pure {
|
||
| 266 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
|
||
| 267 |
} |
||
| 268 | |||
| 269 |
function log(address p0, address p1) internal pure {
|
||
| 270 |
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
|
||
| 271 |
} |
||
| 272 | |||
| 273 |
function log(uint p0, uint p1, uint p2) internal pure {
|
||
| 274 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
|
||
| 275 |
} |
||
| 276 | |||
| 277 |
function log(uint p0, uint p1, string memory p2) internal pure {
|
||
| 278 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
|
||
| 279 |
} |
||
| 280 | |||
| 281 |
function log(uint p0, uint p1, bool p2) internal pure {
|
||
| 282 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
|
||
| 283 |
} |
||
| 284 | |||
| 285 |
function log(uint p0, uint p1, address p2) internal pure {
|
||
| 286 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
|
||
| 287 |
} |
||
| 288 | |||
| 289 |
function log(uint p0, string memory p1, uint p2) internal pure {
|
||
| 290 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
|
||
| 291 |
} |
||
| 292 | |||
| 293 |
function log(uint p0, string memory p1, string memory p2) internal pure {
|
||
| 294 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
|
||
| 295 |
} |
||
| 296 | |||
| 297 |
function log(uint p0, string memory p1, bool p2) internal pure {
|
||
| 298 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
|
||
| 299 |
} |
||
| 300 | |||
| 301 |
function log(uint p0, string memory p1, address p2) internal pure {
|
||
| 302 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
|
||
| 303 |
} |
||
| 304 | |||
| 305 |
function log(uint p0, bool p1, uint p2) internal pure {
|
||
| 306 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
|
||
| 307 |
} |
||
| 308 | |||
| 309 |
function log(uint p0, bool p1, string memory p2) internal pure {
|
||
| 310 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
|
||
| 311 |
} |
||
| 312 | |||
| 313 |
function log(uint p0, bool p1, bool p2) internal pure {
|
||
| 314 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
|
||
| 315 |
} |
||
| 316 | |||
| 317 |
function log(uint p0, bool p1, address p2) internal pure {
|
||
| 318 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
|
||
| 319 |
} |
||
| 320 | |||
| 321 |
function log(uint p0, address p1, uint p2) internal pure {
|
||
| 322 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
|
||
| 323 |
} |
||
| 324 | |||
| 325 |
function log(uint p0, address p1, string memory p2) internal pure {
|
||
| 326 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
|
||
| 327 |
} |
||
| 328 | |||
| 329 |
function log(uint p0, address p1, bool p2) internal pure {
|
||
| 330 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
|
||
| 331 |
} |
||
| 332 | |||
| 333 |
function log(uint p0, address p1, address p2) internal pure {
|
||
| 334 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
|
||
| 335 |
} |
||
| 336 | |||
| 337 |
function log(string memory p0, uint p1, uint p2) internal pure {
|
||
| 338 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
|
||
| 339 |
} |
||
| 340 | |||
| 341 |
function log(string memory p0, uint p1, string memory p2) internal pure {
|
||
| 342 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
|
||
| 343 |
} |
||
| 344 | |||
| 345 |
function log(string memory p0, uint p1, bool p2) internal pure {
|
||
| 346 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
|
||
| 347 |
} |
||
| 348 | |||
| 349 |
function log(string memory p0, uint p1, address p2) internal pure {
|
||
| 350 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
|
||
| 351 |
} |
||
| 352 | |||
| 353 |
function log(string memory p0, string memory p1, uint p2) internal pure {
|
||
| 354 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
|
||
| 355 |
} |
||
| 356 | |||
| 357 |
function log(string memory p0, string memory p1, string memory p2) internal pure {
|
||
| 358 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
|
||
| 359 |
} |
||
| 360 | |||
| 361 |
function log(string memory p0, string memory p1, bool p2) internal pure {
|
||
| 362 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
|
||
| 363 |
} |
||
| 364 | |||
| 365 |
function log(string memory p0, string memory p1, address p2) internal pure {
|
||
| 366 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
|
||
| 367 |
} |
||
| 368 | |||
| 369 |
function log(string memory p0, bool p1, uint p2) internal pure {
|
||
| 370 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
|
||
| 371 |
} |
||
| 372 | |||
| 373 |
function log(string memory p0, bool p1, string memory p2) internal pure {
|
||
| 374 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
|
||
| 375 |
} |
||
| 376 | |||
| 377 |
function log(string memory p0, bool p1, bool p2) internal pure {
|
||
| 378 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
|
||
| 379 |
} |
||
| 380 | |||
| 381 |
function log(string memory p0, bool p1, address p2) internal pure {
|
||
| 382 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
|
||
| 383 |
} |
||
| 384 | |||
| 385 |
function log(string memory p0, address p1, uint p2) internal pure {
|
||
| 386 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
|
||
| 387 |
} |
||
| 388 | |||
| 389 |
function log(string memory p0, address p1, string memory p2) internal pure {
|
||
| 390 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
|
||
| 391 |
} |
||
| 392 | |||
| 393 |
function log(string memory p0, address p1, bool p2) internal pure {
|
||
| 394 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
|
||
| 395 |
} |
||
| 396 | |||
| 397 |
function log(string memory p0, address p1, address p2) internal pure {
|
||
| 398 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
|
||
| 399 |
} |
||
| 400 | |||
| 401 |
function log(bool p0, uint p1, uint p2) internal pure {
|
||
| 402 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
|
||
| 403 |
} |
||
| 404 | |||
| 405 |
function log(bool p0, uint p1, string memory p2) internal pure {
|
||
| 406 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
|
||
| 407 |
} |
||
| 408 | |||
| 409 |
function log(bool p0, uint p1, bool p2) internal pure {
|
||
| 410 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
|
||
| 411 |
} |
||
| 412 | |||
| 413 |
function log(bool p0, uint p1, address p2) internal pure {
|
||
| 414 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
|
||
| 415 |
} |
||
| 416 | |||
| 417 |
function log(bool p0, string memory p1, uint p2) internal pure {
|
||
| 418 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
|
||
| 419 |
} |
||
| 420 | |||
| 421 |
function log(bool p0, string memory p1, string memory p2) internal pure {
|
||
| 422 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
|
||
| 423 |
} |
||
| 424 | |||
| 425 |
function log(bool p0, string memory p1, bool p2) internal pure {
|
||
| 426 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
|
||
| 427 |
} |
||
| 428 | |||
| 429 |
function log(bool p0, string memory p1, address p2) internal pure {
|
||
| 430 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
|
||
| 431 |
} |
||
| 432 | |||
| 433 |
function log(bool p0, bool p1, uint p2) internal pure {
|
||
| 434 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
|
||
| 435 |
} |
||
| 436 | |||
| 437 |
function log(bool p0, bool p1, string memory p2) internal pure {
|
||
| 438 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
|
||
| 439 |
} |
||
| 440 | |||
| 441 |
function log(bool p0, bool p1, bool p2) internal pure {
|
||
| 442 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
|
||
| 443 |
} |
||
| 444 | |||
| 445 |
function log(bool p0, bool p1, address p2) internal pure {
|
||
| 446 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
|
||
| 447 |
} |
||
| 448 | |||
| 449 |
function log(bool p0, address p1, uint p2) internal pure {
|
||
| 450 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
|
||
| 451 |
} |
||
| 452 | |||
| 453 |
function log(bool p0, address p1, string memory p2) internal pure {
|
||
| 454 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
|
||
| 455 |
} |
||
| 456 | |||
| 457 |
function log(bool p0, address p1, bool p2) internal pure {
|
||
| 458 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
|
||
| 459 |
} |
||
| 460 | |||
| 461 |
function log(bool p0, address p1, address p2) internal pure {
|
||
| 462 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
|
||
| 463 |
} |
||
| 464 | |||
| 465 |
function log(address p0, uint p1, uint p2) internal pure {
|
||
| 466 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
|
||
| 467 |
} |
||
| 468 | |||
| 469 |
function log(address p0, uint p1, string memory p2) internal pure {
|
||
| 470 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
|
||
| 471 |
} |
||
| 472 | |||
| 473 |
function log(address p0, uint p1, bool p2) internal pure {
|
||
| 474 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
|
||
| 475 |
} |
||
| 476 | |||
| 477 |
function log(address p0, uint p1, address p2) internal pure {
|
||
| 478 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
|
||
| 479 |
} |
||
| 480 | |||
| 481 |
function log(address p0, string memory p1, uint p2) internal pure {
|
||
| 482 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
|
||
| 483 |
} |
||
| 484 | |||
| 485 |
function log(address p0, string memory p1, string memory p2) internal pure {
|
||
| 486 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
|
||
| 487 |
} |
||
| 488 | |||
| 489 |
function log(address p0, string memory p1, bool p2) internal pure {
|
||
| 490 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
|
||
| 491 |
} |
||
| 492 | |||
| 493 |
function log(address p0, string memory p1, address p2) internal pure {
|
||
| 494 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
|
||
| 495 |
} |
||
| 496 | |||
| 497 |
function log(address p0, bool p1, uint p2) internal pure {
|
||
| 498 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
|
||
| 499 |
} |
||
| 500 | |||
| 501 |
function log(address p0, bool p1, string memory p2) internal pure {
|
||
| 502 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
|
||
| 503 |
} |
||
| 504 | |||
| 505 |
function log(address p0, bool p1, bool p2) internal pure {
|
||
| 506 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
|
||
| 507 |
} |
||
| 508 | |||
| 509 |
function log(address p0, bool p1, address p2) internal pure {
|
||
| 510 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
|
||
| 511 |
} |
||
| 512 | |||
| 513 |
function log(address p0, address p1, uint p2) internal pure {
|
||
| 514 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
|
||
| 515 |
} |
||
| 516 | |||
| 517 |
function log(address p0, address p1, string memory p2) internal pure {
|
||
| 518 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
|
||
| 519 |
} |
||
| 520 | |||
| 521 |
function log(address p0, address p1, bool p2) internal pure {
|
||
| 522 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
|
||
| 523 |
} |
||
| 524 | |||
| 525 |
function log(address p0, address p1, address p2) internal pure {
|
||
| 526 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
|
||
| 527 |
} |
||
| 528 | |||
| 529 |
function log(uint p0, uint p1, uint p2, uint p3) internal pure {
|
||
| 530 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
|
||
| 531 |
} |
||
| 532 | |||
| 533 |
function log(uint p0, uint p1, uint p2, string memory p3) internal pure {
|
||
| 534 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
|
||
| 535 |
} |
||
| 536 | |||
| 537 |
function log(uint p0, uint p1, uint p2, bool p3) internal pure {
|
||
| 538 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
|
||
| 539 |
} |
||
| 540 | |||
| 541 |
function log(uint p0, uint p1, uint p2, address p3) internal pure {
|
||
| 542 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
|
||
| 543 |
} |
||
| 544 | |||
| 545 |
function log(uint p0, uint p1, string memory p2, uint p3) internal pure {
|
||
| 546 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
|
||
| 547 |
} |
||
| 548 | |||
| 549 |
function log(uint p0, uint p1, string memory p2, string memory p3) internal pure {
|
||
| 550 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
|
||
| 551 |
} |
||
| 552 | |||
| 553 |
function log(uint p0, uint p1, string memory p2, bool p3) internal pure {
|
||
| 554 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
|
||
| 555 |
} |
||
| 556 | |||
| 557 |
function log(uint p0, uint p1, string memory p2, address p3) internal pure {
|
||
| 558 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
|
||
| 559 |
} |
||
| 560 | |||
| 561 |
function log(uint p0, uint p1, bool p2, uint p3) internal pure {
|
||
| 562 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
|
||
| 563 |
} |
||
| 564 | |||
| 565 |
function log(uint p0, uint p1, bool p2, string memory p3) internal pure {
|
||
| 566 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
|
||
| 567 |
} |
||
| 568 | |||
| 569 |
function log(uint p0, uint p1, bool p2, bool p3) internal pure {
|
||
| 570 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
|
||
| 571 |
} |
||
| 572 | |||
| 573 |
function log(uint p0, uint p1, bool p2, address p3) internal pure {
|
||
| 574 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
|
||
| 575 |
} |
||
| 576 | |||
| 577 |
function log(uint p0, uint p1, address p2, uint p3) internal pure {
|
||
| 578 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
|
||
| 579 |
} |
||
| 580 | |||
| 581 |
function log(uint p0, uint p1, address p2, string memory p3) internal pure {
|
||
| 582 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
|
||
| 583 |
} |
||
| 584 | |||
| 585 |
function log(uint p0, uint p1, address p2, bool p3) internal pure {
|
||
| 586 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
|
||
| 587 |
} |
||
| 588 | |||
| 589 |
function log(uint p0, uint p1, address p2, address p3) internal pure {
|
||
| 590 |
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
|
||
| 591 |
} |
||
| 592 | |||
| 593 |
function log(uint p0, string memory p1, uint p2, uint p3) internal pure {
|
||
| 594 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
|
||
| 595 |
} |
||
| 596 | |||
| 597 |
function log(uint p0, string memory p1, uint p2, string memory p3) internal pure {
|
||
| 598 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
|
||
| 599 |
} |
||
| 600 | |||
| 601 |
function log(uint p0, string memory p1, uint p2, bool p3) internal pure {
|
||
| 602 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
|
||
| 603 |
} |
||
| 604 | |||
| 605 |
function log(uint p0, string memory p1, uint p2, address p3) internal pure {
|
||
| 606 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
|
||
| 607 |
} |
||
| 608 | |||
| 609 |
function log(uint p0, string memory p1, string memory p2, uint p3) internal pure {
|
||
| 610 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
|
||
| 611 |
} |
||
| 612 | |||
| 613 |
function log(uint p0, string memory p1, string memory p2, string memory p3) internal pure {
|
||
| 614 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
|
||
| 615 |
} |
||
| 616 | |||
| 617 |
function log(uint p0, string memory p1, string memory p2, bool p3) internal pure {
|
||
| 618 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
|
||
| 619 |
} |
||
| 620 | |||
| 621 |
function log(uint p0, string memory p1, string memory p2, address p3) internal pure {
|
||
| 622 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
|
||
| 623 |
} |
||
| 624 | |||
| 625 |
function log(uint p0, string memory p1, bool p2, uint p3) internal pure {
|
||
| 626 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
|
||
| 627 |
} |
||
| 628 | |||
| 629 |
function log(uint p0, string memory p1, bool p2, string memory p3) internal pure {
|
||
| 630 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
|
||
| 631 |
} |
||
| 632 | |||
| 633 |
function log(uint p0, string memory p1, bool p2, bool p3) internal pure {
|
||
| 634 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
|
||
| 635 |
} |
||
| 636 | |||
| 637 |
function log(uint p0, string memory p1, bool p2, address p3) internal pure {
|
||
| 638 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
|
||
| 639 |
} |
||
| 640 | |||
| 641 |
function log(uint p0, string memory p1, address p2, uint p3) internal pure {
|
||
| 642 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
|
||
| 643 |
} |
||
| 644 | |||
| 645 |
function log(uint p0, string memory p1, address p2, string memory p3) internal pure {
|
||
| 646 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
|
||
| 647 |
} |
||
| 648 | |||
| 649 |
function log(uint p0, string memory p1, address p2, bool p3) internal pure {
|
||
| 650 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
|
||
| 651 |
} |
||
| 652 | |||
| 653 |
function log(uint p0, string memory p1, address p2, address p3) internal pure {
|
||
| 654 |
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
|
||
| 655 |
} |
||
| 656 | |||
| 657 |
function log(uint p0, bool p1, uint p2, uint p3) internal pure {
|
||
| 658 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
|
||
| 659 |
} |
||
| 660 | |||
| 661 |
function log(uint p0, bool p1, uint p2, string memory p3) internal pure {
|
||
| 662 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
|
||
| 663 |
} |
||
| 664 | |||
| 665 |
function log(uint p0, bool p1, uint p2, bool p3) internal pure {
|
||
| 666 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
|
||
| 667 |
} |
||
| 668 | |||
| 669 |
function log(uint p0, bool p1, uint p2, address p3) internal pure {
|
||
| 670 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
|
||
| 671 |
} |
||
| 672 | |||
| 673 |
function log(uint p0, bool p1, string memory p2, uint p3) internal pure {
|
||
| 674 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
|
||
| 675 |
} |
||
| 676 | |||
| 677 |
function log(uint p0, bool p1, string memory p2, string memory p3) internal pure {
|
||
| 678 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
|
||
| 679 |
} |
||
| 680 | |||
| 681 |
function log(uint p0, bool p1, string memory p2, bool p3) internal pure {
|
||
| 682 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
|
||
| 683 |
} |
||
| 684 | |||
| 685 |
function log(uint p0, bool p1, string memory p2, address p3) internal pure {
|
||
| 686 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
|
||
| 687 |
} |
||
| 688 | |||
| 689 |
function log(uint p0, bool p1, bool p2, uint p3) internal pure {
|
||
| 690 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
|
||
| 691 |
} |
||
| 692 | |||
| 693 |
function log(uint p0, bool p1, bool p2, string memory p3) internal pure {
|
||
| 694 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
|
||
| 695 |
} |
||
| 696 | |||
| 697 |
function log(uint p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 698 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
|
||
| 699 |
} |
||
| 700 | |||
| 701 |
function log(uint p0, bool p1, bool p2, address p3) internal pure {
|
||
| 702 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
|
||
| 703 |
} |
||
| 704 | |||
| 705 |
function log(uint p0, bool p1, address p2, uint p3) internal pure {
|
||
| 706 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
|
||
| 707 |
} |
||
| 708 | |||
| 709 |
function log(uint p0, bool p1, address p2, string memory p3) internal pure {
|
||
| 710 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
|
||
| 711 |
} |
||
| 712 | |||
| 713 |
function log(uint p0, bool p1, address p2, bool p3) internal pure {
|
||
| 714 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
|
||
| 715 |
} |
||
| 716 | |||
| 717 |
function log(uint p0, bool p1, address p2, address p3) internal pure {
|
||
| 718 |
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
|
||
| 719 |
} |
||
| 720 | |||
| 721 |
function log(uint p0, address p1, uint p2, uint p3) internal pure {
|
||
| 722 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
|
||
| 723 |
} |
||
| 724 | |||
| 725 |
function log(uint p0, address p1, uint p2, string memory p3) internal pure {
|
||
| 726 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
|
||
| 727 |
} |
||
| 728 | |||
| 729 |
function log(uint p0, address p1, uint p2, bool p3) internal pure {
|
||
| 730 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
|
||
| 731 |
} |
||
| 732 | |||
| 733 |
function log(uint p0, address p1, uint p2, address p3) internal pure {
|
||
| 734 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
|
||
| 735 |
} |
||
| 736 | |||
| 737 |
function log(uint p0, address p1, string memory p2, uint p3) internal pure {
|
||
| 738 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
|
||
| 739 |
} |
||
| 740 | |||
| 741 |
function log(uint p0, address p1, string memory p2, string memory p3) internal pure {
|
||
| 742 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
|
||
| 743 |
} |
||
| 744 | |||
| 745 |
function log(uint p0, address p1, string memory p2, bool p3) internal pure {
|
||
| 746 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
|
||
| 747 |
} |
||
| 748 | |||
| 749 |
function log(uint p0, address p1, string memory p2, address p3) internal pure {
|
||
| 750 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
|
||
| 751 |
} |
||
| 752 | |||
| 753 |
function log(uint p0, address p1, bool p2, uint p3) internal pure {
|
||
| 754 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
|
||
| 755 |
} |
||
| 756 | |||
| 757 |
function log(uint p0, address p1, bool p2, string memory p3) internal pure {
|
||
| 758 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
|
||
| 759 |
} |
||
| 760 | |||
| 761 |
function log(uint p0, address p1, bool p2, bool p3) internal pure {
|
||
| 762 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
|
||
| 763 |
} |
||
| 764 | |||
| 765 |
function log(uint p0, address p1, bool p2, address p3) internal pure {
|
||
| 766 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
|
||
| 767 |
} |
||
| 768 | |||
| 769 |
function log(uint p0, address p1, address p2, uint p3) internal pure {
|
||
| 770 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
|
||
| 771 |
} |
||
| 772 | |||
| 773 |
function log(uint p0, address p1, address p2, string memory p3) internal pure {
|
||
| 774 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
|
||
| 775 |
} |
||
| 776 | |||
| 777 |
function log(uint p0, address p1, address p2, bool p3) internal pure {
|
||
| 778 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
|
||
| 779 |
} |
||
| 780 | |||
| 781 |
function log(uint p0, address p1, address p2, address p3) internal pure {
|
||
| 782 |
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
|
||
| 783 |
} |
||
| 784 | |||
| 785 |
function log(string memory p0, uint p1, uint p2, uint p3) internal pure {
|
||
| 786 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
|
||
| 787 |
} |
||
| 788 | |||
| 789 |
function log(string memory p0, uint p1, uint p2, string memory p3) internal pure {
|
||
| 790 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
|
||
| 791 |
} |
||
| 792 | |||
| 793 |
function log(string memory p0, uint p1, uint p2, bool p3) internal pure {
|
||
| 794 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
|
||
| 795 |
} |
||
| 796 | |||
| 797 |
function log(string memory p0, uint p1, uint p2, address p3) internal pure {
|
||
| 798 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
|
||
| 799 |
} |
||
| 800 | |||
| 801 |
function log(string memory p0, uint p1, string memory p2, uint p3) internal pure {
|
||
| 802 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
|
||
| 803 |
} |
||
| 804 | |||
| 805 |
function log(string memory p0, uint p1, string memory p2, string memory p3) internal pure {
|
||
| 806 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
|
||
| 807 |
} |
||
| 808 | |||
| 809 |
function log(string memory p0, uint p1, string memory p2, bool p3) internal pure {
|
||
| 810 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
|
||
| 811 |
} |
||
| 812 | |||
| 813 |
function log(string memory p0, uint p1, string memory p2, address p3) internal pure {
|
||
| 814 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
|
||
| 815 |
} |
||
| 816 | |||
| 817 |
function log(string memory p0, uint p1, bool p2, uint p3) internal pure {
|
||
| 818 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
|
||
| 819 |
} |
||
| 820 | |||
| 821 |
function log(string memory p0, uint p1, bool p2, string memory p3) internal pure {
|
||
| 822 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
|
||
| 823 |
} |
||
| 824 | |||
| 825 |
function log(string memory p0, uint p1, bool p2, bool p3) internal pure {
|
||
| 826 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
|
||
| 827 |
} |
||
| 828 | |||
| 829 |
function log(string memory p0, uint p1, bool p2, address p3) internal pure {
|
||
| 830 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
|
||
| 831 |
} |
||
| 832 | |||
| 833 |
function log(string memory p0, uint p1, address p2, uint p3) internal pure {
|
||
| 834 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
|
||
| 835 |
} |
||
| 836 | |||
| 837 |
function log(string memory p0, uint p1, address p2, string memory p3) internal pure {
|
||
| 838 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
|
||
| 839 |
} |
||
| 840 | |||
| 841 |
function log(string memory p0, uint p1, address p2, bool p3) internal pure {
|
||
| 842 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
|
||
| 843 |
} |
||
| 844 | |||
| 845 |
function log(string memory p0, uint p1, address p2, address p3) internal pure {
|
||
| 846 |
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
|
||
| 847 |
} |
||
| 848 | |||
| 849 |
function log(string memory p0, string memory p1, uint p2, uint p3) internal pure {
|
||
| 850 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
|
||
| 851 |
} |
||
| 852 | |||
| 853 |
function log(string memory p0, string memory p1, uint p2, string memory p3) internal pure {
|
||
| 854 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
|
||
| 855 |
} |
||
| 856 | |||
| 857 |
function log(string memory p0, string memory p1, uint p2, bool p3) internal pure {
|
||
| 858 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
|
||
| 859 |
} |
||
| 860 | |||
| 861 |
function log(string memory p0, string memory p1, uint p2, address p3) internal pure {
|
||
| 862 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
|
||
| 863 |
} |
||
| 864 | |||
| 865 |
function log(string memory p0, string memory p1, string memory p2, uint p3) internal pure {
|
||
| 866 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
|
||
| 867 |
} |
||
| 868 | |||
| 869 |
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
|
||
| 870 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
|
||
| 871 |
} |
||
| 872 | |||
| 873 |
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
|
||
| 874 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
|
||
| 875 |
} |
||
| 876 | |||
| 877 |
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
|
||
| 878 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
|
||
| 879 |
} |
||
| 880 | |||
| 881 |
function log(string memory p0, string memory p1, bool p2, uint p3) internal pure {
|
||
| 882 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
|
||
| 883 |
} |
||
| 884 | |||
| 885 |
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
|
||
| 886 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
|
||
| 887 |
} |
||
| 888 | |||
| 889 |
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
|
||
| 890 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
|
||
| 891 |
} |
||
| 892 | |||
| 893 |
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
|
||
| 894 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
|
||
| 895 |
} |
||
| 896 | |||
| 897 |
function log(string memory p0, string memory p1, address p2, uint p3) internal pure {
|
||
| 898 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
|
||
| 899 |
} |
||
| 900 | |||
| 901 |
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
|
||
| 902 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
|
||
| 903 |
} |
||
| 904 | |||
| 905 |
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
|
||
| 906 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
|
||
| 907 |
} |
||
| 908 | |||
| 909 |
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
|
||
| 910 |
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
|
||
| 911 |
} |
||
| 912 | |||
| 913 |
function log(string memory p0, bool p1, uint p2, uint p3) internal pure {
|
||
| 914 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
|
||
| 915 |
} |
||
| 916 | |||
| 917 |
function log(string memory p0, bool p1, uint p2, string memory p3) internal pure {
|
||
| 918 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
|
||
| 919 |
} |
||
| 920 | |||
| 921 |
function log(string memory p0, bool p1, uint p2, bool p3) internal pure {
|
||
| 922 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
|
||
| 923 |
} |
||
| 924 | |||
| 925 |
function log(string memory p0, bool p1, uint p2, address p3) internal pure {
|
||
| 926 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
|
||
| 927 |
} |
||
| 928 | |||
| 929 |
function log(string memory p0, bool p1, string memory p2, uint p3) internal pure {
|
||
| 930 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
|
||
| 931 |
} |
||
| 932 | |||
| 933 |
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
|
||
| 934 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
|
||
| 935 |
} |
||
| 936 | |||
| 937 |
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
|
||
| 938 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
|
||
| 939 |
} |
||
| 940 | |||
| 941 |
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
|
||
| 942 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
|
||
| 943 |
} |
||
| 944 | |||
| 945 |
function log(string memory p0, bool p1, bool p2, uint p3) internal pure {
|
||
| 946 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
|
||
| 947 |
} |
||
| 948 | |||
| 949 |
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
|
||
| 950 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
|
||
| 951 |
} |
||
| 952 | |||
| 953 |
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 954 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
|
||
| 955 |
} |
||
| 956 | |||
| 957 |
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
|
||
| 958 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
|
||
| 959 |
} |
||
| 960 | |||
| 961 |
function log(string memory p0, bool p1, address p2, uint p3) internal pure {
|
||
| 962 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
|
||
| 963 |
} |
||
| 964 | |||
| 965 |
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
|
||
| 966 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
|
||
| 967 |
} |
||
| 968 | |||
| 969 |
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
|
||
| 970 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
|
||
| 971 |
} |
||
| 972 | |||
| 973 |
function log(string memory p0, bool p1, address p2, address p3) internal pure {
|
||
| 974 |
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
|
||
| 975 |
} |
||
| 976 | |||
| 977 |
function log(string memory p0, address p1, uint p2, uint p3) internal pure {
|
||
| 978 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
|
||
| 979 |
} |
||
| 980 | |||
| 981 |
function log(string memory p0, address p1, uint p2, string memory p3) internal pure {
|
||
| 982 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
|
||
| 983 |
} |
||
| 984 | |||
| 985 |
function log(string memory p0, address p1, uint p2, bool p3) internal pure {
|
||
| 986 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
|
||
| 987 |
} |
||
| 988 | |||
| 989 |
function log(string memory p0, address p1, uint p2, address p3) internal pure {
|
||
| 990 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
|
||
| 991 |
} |
||
| 992 | |||
| 993 |
function log(string memory p0, address p1, string memory p2, uint p3) internal pure {
|
||
| 994 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
|
||
| 995 |
} |
||
| 996 | |||
| 997 |
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
|
||
| 998 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
|
||
| 999 |
} |
||
| 1000 | |||
| 1001 |
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
|
||
| 1002 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
|
||
| 1003 |
} |
||
| 1004 | |||
| 1005 |
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
|
||
| 1006 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
|
||
| 1007 |
} |
||
| 1008 | |||
| 1009 |
function log(string memory p0, address p1, bool p2, uint p3) internal pure {
|
||
| 1010 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
|
||
| 1011 |
} |
||
| 1012 | |||
| 1013 |
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
|
||
| 1014 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
|
||
| 1015 |
} |
||
| 1016 | |||
| 1017 |
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
|
||
| 1018 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
|
||
| 1019 |
} |
||
| 1020 | |||
| 1021 |
function log(string memory p0, address p1, bool p2, address p3) internal pure {
|
||
| 1022 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
|
||
| 1023 |
} |
||
| 1024 | |||
| 1025 |
function log(string memory p0, address p1, address p2, uint p3) internal pure {
|
||
| 1026 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
|
||
| 1027 |
} |
||
| 1028 | |||
| 1029 |
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
|
||
| 1030 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
|
||
| 1031 |
} |
||
| 1032 | |||
| 1033 |
function log(string memory p0, address p1, address p2, bool p3) internal pure {
|
||
| 1034 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
|
||
| 1035 |
} |
||
| 1036 | |||
| 1037 |
function log(string memory p0, address p1, address p2, address p3) internal pure {
|
||
| 1038 |
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
|
||
| 1039 |
} |
||
| 1040 | |||
| 1041 |
function log(bool p0, uint p1, uint p2, uint p3) internal pure {
|
||
| 1042 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
|
||
| 1043 |
} |
||
| 1044 | |||
| 1045 |
function log(bool p0, uint p1, uint p2, string memory p3) internal pure {
|
||
| 1046 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
|
||
| 1047 |
} |
||
| 1048 | |||
| 1049 |
function log(bool p0, uint p1, uint p2, bool p3) internal pure {
|
||
| 1050 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
|
||
| 1051 |
} |
||
| 1052 | |||
| 1053 |
function log(bool p0, uint p1, uint p2, address p3) internal pure {
|
||
| 1054 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
|
||
| 1055 |
} |
||
| 1056 | |||
| 1057 |
function log(bool p0, uint p1, string memory p2, uint p3) internal pure {
|
||
| 1058 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
|
||
| 1059 |
} |
||
| 1060 | |||
| 1061 |
function log(bool p0, uint p1, string memory p2, string memory p3) internal pure {
|
||
| 1062 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
|
||
| 1063 |
} |
||
| 1064 | |||
| 1065 |
function log(bool p0, uint p1, string memory p2, bool p3) internal pure {
|
||
| 1066 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
|
||
| 1067 |
} |
||
| 1068 | |||
| 1069 |
function log(bool p0, uint p1, string memory p2, address p3) internal pure {
|
||
| 1070 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
|
||
| 1071 |
} |
||
| 1072 | |||
| 1073 |
function log(bool p0, uint p1, bool p2, uint p3) internal pure {
|
||
| 1074 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
|
||
| 1075 |
} |
||
| 1076 | |||
| 1077 |
function log(bool p0, uint p1, bool p2, string memory p3) internal pure {
|
||
| 1078 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
|
||
| 1079 |
} |
||
| 1080 | |||
| 1081 |
function log(bool p0, uint p1, bool p2, bool p3) internal pure {
|
||
| 1082 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
|
||
| 1083 |
} |
||
| 1084 | |||
| 1085 |
function log(bool p0, uint p1, bool p2, address p3) internal pure {
|
||
| 1086 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
|
||
| 1087 |
} |
||
| 1088 | |||
| 1089 |
function log(bool p0, uint p1, address p2, uint p3) internal pure {
|
||
| 1090 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
|
||
| 1091 |
} |
||
| 1092 | |||
| 1093 |
function log(bool p0, uint p1, address p2, string memory p3) internal pure {
|
||
| 1094 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
|
||
| 1095 |
} |
||
| 1096 | |||
| 1097 |
function log(bool p0, uint p1, address p2, bool p3) internal pure {
|
||
| 1098 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
|
||
| 1099 |
} |
||
| 1100 | |||
| 1101 |
function log(bool p0, uint p1, address p2, address p3) internal pure {
|
||
| 1102 |
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
|
||
| 1103 |
} |
||
| 1104 | |||
| 1105 |
function log(bool p0, string memory p1, uint p2, uint p3) internal pure {
|
||
| 1106 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
|
||
| 1107 |
} |
||
| 1108 | |||
| 1109 |
function log(bool p0, string memory p1, uint p2, string memory p3) internal pure {
|
||
| 1110 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
|
||
| 1111 |
} |
||
| 1112 | |||
| 1113 |
function log(bool p0, string memory p1, uint p2, bool p3) internal pure {
|
||
| 1114 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
|
||
| 1115 |
} |
||
| 1116 | |||
| 1117 |
function log(bool p0, string memory p1, uint p2, address p3) internal pure {
|
||
| 1118 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
|
||
| 1119 |
} |
||
| 1120 | |||
| 1121 |
function log(bool p0, string memory p1, string memory p2, uint p3) internal pure {
|
||
| 1122 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
|
||
| 1123 |
} |
||
| 1124 | |||
| 1125 |
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
|
||
| 1126 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
|
||
| 1127 |
} |
||
| 1128 | |||
| 1129 |
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
|
||
| 1130 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
|
||
| 1131 |
} |
||
| 1132 | |||
| 1133 |
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
|
||
| 1134 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
|
||
| 1135 |
} |
||
| 1136 | |||
| 1137 |
function log(bool p0, string memory p1, bool p2, uint p3) internal pure {
|
||
| 1138 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
|
||
| 1139 |
} |
||
| 1140 | |||
| 1141 |
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
|
||
| 1142 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
|
||
| 1143 |
} |
||
| 1144 | |||
| 1145 |
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
|
||
| 1146 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
|
||
| 1147 |
} |
||
| 1148 | |||
| 1149 |
function log(bool p0, string memory p1, bool p2, address p3) internal pure {
|
||
| 1150 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
|
||
| 1151 |
} |
||
| 1152 | |||
| 1153 |
function log(bool p0, string memory p1, address p2, uint p3) internal pure {
|
||
| 1154 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
|
||
| 1155 |
} |
||
| 1156 | |||
| 1157 |
function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
|
||
| 1158 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
|
||
| 1159 |
} |
||
| 1160 | |||
| 1161 |
function log(bool p0, string memory p1, address p2, bool p3) internal pure {
|
||
| 1162 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
|
||
| 1163 |
} |
||
| 1164 | |||
| 1165 |
function log(bool p0, string memory p1, address p2, address p3) internal pure {
|
||
| 1166 |
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
|
||
| 1167 |
} |
||
| 1168 | |||
| 1169 |
function log(bool p0, bool p1, uint p2, uint p3) internal pure {
|
||
| 1170 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
|
||
| 1171 |
} |
||
| 1172 | |||
| 1173 |
function log(bool p0, bool p1, uint p2, string memory p3) internal pure {
|
||
| 1174 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
|
||
| 1175 |
} |
||
| 1176 | |||
| 1177 |
function log(bool p0, bool p1, uint p2, bool p3) internal pure {
|
||
| 1178 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
|
||
| 1179 |
} |
||
| 1180 | |||
| 1181 |
function log(bool p0, bool p1, uint p2, address p3) internal pure {
|
||
| 1182 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
|
||
| 1183 |
} |
||
| 1184 | |||
| 1185 |
function log(bool p0, bool p1, string memory p2, uint p3) internal pure {
|
||
| 1186 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
|
||
| 1187 |
} |
||
| 1188 | |||
| 1189 |
function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
|
||
| 1190 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
|
||
| 1191 |
} |
||
| 1192 | |||
| 1193 |
function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
|
||
| 1194 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
|
||
| 1195 |
} |
||
| 1196 | |||
| 1197 |
function log(bool p0, bool p1, string memory p2, address p3) internal pure {
|
||
| 1198 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
|
||
| 1199 |
} |
||
| 1200 | |||
| 1201 |
function log(bool p0, bool p1, bool p2, uint p3) internal pure {
|
||
| 1202 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
|
||
| 1203 |
} |
||
| 1204 | |||
| 1205 |
function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
|
||
| 1206 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
|
||
| 1207 |
} |
||
| 1208 | |||
| 1209 |
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 1210 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
|
||
| 1211 |
} |
||
| 1212 | |||
| 1213 |
function log(bool p0, bool p1, bool p2, address p3) internal pure {
|
||
| 1214 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
|
||
| 1215 |
} |
||
| 1216 | |||
| 1217 |
function log(bool p0, bool p1, address p2, uint p3) internal pure {
|
||
| 1218 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
|
||
| 1219 |
} |
||
| 1220 | |||
| 1221 |
function log(bool p0, bool p1, address p2, string memory p3) internal pure {
|
||
| 1222 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
|
||
| 1223 |
} |
||
| 1224 | |||
| 1225 |
function log(bool p0, bool p1, address p2, bool p3) internal pure {
|
||
| 1226 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
|
||
| 1227 |
} |
||
| 1228 | |||
| 1229 |
function log(bool p0, bool p1, address p2, address p3) internal pure {
|
||
| 1230 |
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
|
||
| 1231 |
} |
||
| 1232 | |||
| 1233 |
function log(bool p0, address p1, uint p2, uint p3) internal pure {
|
||
| 1234 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
|
||
| 1235 |
} |
||
| 1236 | |||
| 1237 |
function log(bool p0, address p1, uint p2, string memory p3) internal pure {
|
||
| 1238 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
|
||
| 1239 |
} |
||
| 1240 | |||
| 1241 |
function log(bool p0, address p1, uint p2, bool p3) internal pure {
|
||
| 1242 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
|
||
| 1243 |
} |
||
| 1244 | |||
| 1245 |
function log(bool p0, address p1, uint p2, address p3) internal pure {
|
||
| 1246 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
|
||
| 1247 |
} |
||
| 1248 | |||
| 1249 |
function log(bool p0, address p1, string memory p2, uint p3) internal pure {
|
||
| 1250 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
|
||
| 1251 |
} |
||
| 1252 | |||
| 1253 |
function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
|
||
| 1254 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
|
||
| 1255 |
} |
||
| 1256 | |||
| 1257 |
function log(bool p0, address p1, string memory p2, bool p3) internal pure {
|
||
| 1258 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
|
||
| 1259 |
} |
||
| 1260 | |||
| 1261 |
function log(bool p0, address p1, string memory p2, address p3) internal pure {
|
||
| 1262 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
|
||
| 1263 |
} |
||
| 1264 | |||
| 1265 |
function log(bool p0, address p1, bool p2, uint p3) internal pure {
|
||
| 1266 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
|
||
| 1267 |
} |
||
| 1268 | |||
| 1269 |
function log(bool p0, address p1, bool p2, string memory p3) internal pure {
|
||
| 1270 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
|
||
| 1271 |
} |
||
| 1272 | |||
| 1273 |
function log(bool p0, address p1, bool p2, bool p3) internal pure {
|
||
| 1274 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
|
||
| 1275 |
} |
||
| 1276 | |||
| 1277 |
function log(bool p0, address p1, bool p2, address p3) internal pure {
|
||
| 1278 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
|
||
| 1279 |
} |
||
| 1280 | |||
| 1281 |
function log(bool p0, address p1, address p2, uint p3) internal pure {
|
||
| 1282 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
|
||
| 1283 |
} |
||
| 1284 | |||
| 1285 |
function log(bool p0, address p1, address p2, string memory p3) internal pure {
|
||
| 1286 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
|
||
| 1287 |
} |
||
| 1288 | |||
| 1289 |
function log(bool p0, address p1, address p2, bool p3) internal pure {
|
||
| 1290 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
|
||
| 1291 |
} |
||
| 1292 | |||
| 1293 |
function log(bool p0, address p1, address p2, address p3) internal pure {
|
||
| 1294 |
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
|
||
| 1295 |
} |
||
| 1296 | |||
| 1297 |
function log(address p0, uint p1, uint p2, uint p3) internal pure {
|
||
| 1298 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
|
||
| 1299 |
} |
||
| 1300 | |||
| 1301 |
function log(address p0, uint p1, uint p2, string memory p3) internal pure {
|
||
| 1302 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
|
||
| 1303 |
} |
||
| 1304 | |||
| 1305 |
function log(address p0, uint p1, uint p2, bool p3) internal pure {
|
||
| 1306 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
|
||
| 1307 |
} |
||
| 1308 | |||
| 1309 |
function log(address p0, uint p1, uint p2, address p3) internal pure {
|
||
| 1310 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
|
||
| 1311 |
} |
||
| 1312 | |||
| 1313 |
function log(address p0, uint p1, string memory p2, uint p3) internal pure {
|
||
| 1314 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
|
||
| 1315 |
} |
||
| 1316 | |||
| 1317 |
function log(address p0, uint p1, string memory p2, string memory p3) internal pure {
|
||
| 1318 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
|
||
| 1319 |
} |
||
| 1320 | |||
| 1321 |
function log(address p0, uint p1, string memory p2, bool p3) internal pure {
|
||
| 1322 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
|
||
| 1323 |
} |
||
| 1324 | |||
| 1325 |
function log(address p0, uint p1, string memory p2, address p3) internal pure {
|
||
| 1326 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
|
||
| 1327 |
} |
||
| 1328 | |||
| 1329 |
function log(address p0, uint p1, bool p2, uint p3) internal pure {
|
||
| 1330 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
|
||
| 1331 |
} |
||
| 1332 | |||
| 1333 |
function log(address p0, uint p1, bool p2, string memory p3) internal pure {
|
||
| 1334 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
|
||
| 1335 |
} |
||
| 1336 | |||
| 1337 |
function log(address p0, uint p1, bool p2, bool p3) internal pure {
|
||
| 1338 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
|
||
| 1339 |
} |
||
| 1340 | |||
| 1341 |
function log(address p0, uint p1, bool p2, address p3) internal pure {
|
||
| 1342 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
|
||
| 1343 |
} |
||
| 1344 | |||
| 1345 |
function log(address p0, uint p1, address p2, uint p3) internal pure {
|
||
| 1346 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
|
||
| 1347 |
} |
||
| 1348 | |||
| 1349 |
function log(address p0, uint p1, address p2, string memory p3) internal pure {
|
||
| 1350 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
|
||
| 1351 |
} |
||
| 1352 | |||
| 1353 |
function log(address p0, uint p1, address p2, bool p3) internal pure {
|
||
| 1354 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
|
||
| 1355 |
} |
||
| 1356 | |||
| 1357 |
function log(address p0, uint p1, address p2, address p3) internal pure {
|
||
| 1358 |
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
|
||
| 1359 |
} |
||
| 1360 | |||
| 1361 |
function log(address p0, string memory p1, uint p2, uint p3) internal pure {
|
||
| 1362 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
|
||
| 1363 |
} |
||
| 1364 | |||
| 1365 |
function log(address p0, string memory p1, uint p2, string memory p3) internal pure {
|
||
| 1366 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
|
||
| 1367 |
} |
||
| 1368 | |||
| 1369 |
function log(address p0, string memory p1, uint p2, bool p3) internal pure {
|
||
| 1370 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
|
||
| 1371 |
} |
||
| 1372 | |||
| 1373 |
function log(address p0, string memory p1, uint p2, address p3) internal pure {
|
||
| 1374 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
|
||
| 1375 |
} |
||
| 1376 | |||
| 1377 |
function log(address p0, string memory p1, string memory p2, uint p3) internal pure {
|
||
| 1378 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
|
||
| 1379 |
} |
||
| 1380 | |||
| 1381 |
function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
|
||
| 1382 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
|
||
| 1383 |
} |
||
| 1384 | |||
| 1385 |
function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
|
||
| 1386 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
|
||
| 1387 |
} |
||
| 1388 | |||
| 1389 |
function log(address p0, string memory p1, string memory p2, address p3) internal pure {
|
||
| 1390 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
|
||
| 1391 |
} |
||
| 1392 | |||
| 1393 |
function log(address p0, string memory p1, bool p2, uint p3) internal pure {
|
||
| 1394 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
|
||
| 1395 |
} |
||
| 1396 | |||
| 1397 |
function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
|
||
| 1398 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
|
||
| 1399 |
} |
||
| 1400 | |||
| 1401 |
function log(address p0, string memory p1, bool p2, bool p3) internal pure {
|
||
| 1402 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
|
||
| 1403 |
} |
||
| 1404 | |||
| 1405 |
function log(address p0, string memory p1, bool p2, address p3) internal pure {
|
||
| 1406 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
|
||
| 1407 |
} |
||
| 1408 | |||
| 1409 |
function log(address p0, string memory p1, address p2, uint p3) internal pure {
|
||
| 1410 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
|
||
| 1411 |
} |
||
| 1412 | |||
| 1413 |
function log(address p0, string memory p1, address p2, string memory p3) internal pure {
|
||
| 1414 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
|
||
| 1415 |
} |
||
| 1416 | |||
| 1417 |
function log(address p0, string memory p1, address p2, bool p3) internal pure {
|
||
| 1418 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
|
||
| 1419 |
} |
||
| 1420 | |||
| 1421 |
function log(address p0, string memory p1, address p2, address p3) internal pure {
|
||
| 1422 |
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
|
||
| 1423 |
} |
||
| 1424 | |||
| 1425 |
function log(address p0, bool p1, uint p2, uint p3) internal pure {
|
||
| 1426 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
|
||
| 1427 |
} |
||
| 1428 | |||
| 1429 |
function log(address p0, bool p1, uint p2, string memory p3) internal pure {
|
||
| 1430 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
|
||
| 1431 |
} |
||
| 1432 | |||
| 1433 |
function log(address p0, bool p1, uint p2, bool p3) internal pure {
|
||
| 1434 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
|
||
| 1435 |
} |
||
| 1436 | |||
| 1437 |
function log(address p0, bool p1, uint p2, address p3) internal pure {
|
||
| 1438 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
|
||
| 1439 |
} |
||
| 1440 | |||
| 1441 |
function log(address p0, bool p1, string memory p2, uint p3) internal pure {
|
||
| 1442 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
|
||
| 1443 |
} |
||
| 1444 | |||
| 1445 |
function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
|
||
| 1446 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
|
||
| 1447 |
} |
||
| 1448 | |||
| 1449 |
function log(address p0, bool p1, string memory p2, bool p3) internal pure {
|
||
| 1450 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
|
||
| 1451 |
} |
||
| 1452 | |||
| 1453 |
function log(address p0, bool p1, string memory p2, address p3) internal pure {
|
||
| 1454 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
|
||
| 1455 |
} |
||
| 1456 | |||
| 1457 |
function log(address p0, bool p1, bool p2, uint p3) internal pure {
|
||
| 1458 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
|
||
| 1459 |
} |
||
| 1460 | |||
| 1461 |
function log(address p0, bool p1, bool p2, string memory p3) internal pure {
|
||
| 1462 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
|
||
| 1463 |
} |
||
| 1464 | |||
| 1465 |
function log(address p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 1466 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
|
||
| 1467 |
} |
||
| 1468 | |||
| 1469 |
function log(address p0, bool p1, bool p2, address p3) internal pure {
|
||
| 1470 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
|
||
| 1471 |
} |
||
| 1472 | |||
| 1473 |
function log(address p0, bool p1, address p2, uint p3) internal pure {
|
||
| 1474 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
|
||
| 1475 |
} |
||
| 1476 | |||
| 1477 |
function log(address p0, bool p1, address p2, string memory p3) internal pure {
|
||
| 1478 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
|
||
| 1479 |
} |
||
| 1480 | |||
| 1481 |
function log(address p0, bool p1, address p2, bool p3) internal pure {
|
||
| 1482 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
|
||
| 1483 |
} |
||
| 1484 | |||
| 1485 |
function log(address p0, bool p1, address p2, address p3) internal pure {
|
||
| 1486 |
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
|
||
| 1487 |
} |
||
| 1488 | |||
| 1489 |
function log(address p0, address p1, uint p2, uint p3) internal pure {
|
||
| 1490 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
|
||
| 1491 |
} |
||
| 1492 | |||
| 1493 |
function log(address p0, address p1, uint p2, string memory p3) internal pure {
|
||
| 1494 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
|
||
| 1495 |
} |
||
| 1496 | |||
| 1497 |
function log(address p0, address p1, uint p2, bool p3) internal pure {
|
||
| 1498 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
|
||
| 1499 |
} |
||
| 1500 | |||
| 1501 |
function log(address p0, address p1, uint p2, address p3) internal pure {
|
||
| 1502 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
|
||
| 1503 |
} |
||
| 1504 | |||
| 1505 |
function log(address p0, address p1, string memory p2, uint p3) internal pure {
|
||
| 1506 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
|
||
| 1507 |
} |
||
| 1508 | |||
| 1509 |
function log(address p0, address p1, string memory p2, string memory p3) internal pure {
|
||
| 1510 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
|
||
| 1511 |
} |
||
| 1512 | |||
| 1513 |
function log(address p0, address p1, string memory p2, bool p3) internal pure {
|
||
| 1514 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
|
||
| 1515 |
} |
||
| 1516 | |||
| 1517 |
function log(address p0, address p1, string memory p2, address p3) internal pure {
|
||
| 1518 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
|
||
| 1519 |
} |
||
| 1520 | |||
| 1521 |
function log(address p0, address p1, bool p2, uint p3) internal pure {
|
||
| 1522 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
|
||
| 1523 |
} |
||
| 1524 | |||
| 1525 |
function log(address p0, address p1, bool p2, string memory p3) internal pure {
|
||
| 1526 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
|
||
| 1527 |
} |
||
| 1528 | |||
| 1529 |
function log(address p0, address p1, bool p2, bool p3) internal pure {
|
||
| 1530 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
|
||
| 1531 |
} |
||
| 1532 | |||
| 1533 |
function log(address p0, address p1, bool p2, address p3) internal pure {
|
||
| 1534 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
|
||
| 1535 |
} |
||
| 1536 | |||
| 1537 |
function log(address p0, address p1, address p2, uint p3) internal pure {
|
||
| 1538 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
|
||
| 1539 |
} |
||
| 1540 | |||
| 1541 |
function log(address p0, address p1, address p2, string memory p3) internal pure {
|
||
| 1542 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
|
||
| 1543 |
} |
||
| 1544 | |||
| 1545 |
function log(address p0, address p1, address p2, bool p3) internal pure {
|
||
| 1546 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
|
||
| 1547 |
} |
||
| 1548 | |||
| 1549 |
function log(address p0, address p1, address p2, address p3) internal pure {
|
||
| 1550 |
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
|
||
| 1551 |
} |
||
| 1552 |
} |
||
| 1553 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.4.22 <0.9.0; |
||
| 3 | |||
| 4 |
import {console as console2} from "./console.sol";
|
||
| 5 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2; |
||
| 3 | |||
| 4 |
interface IERC165 {
|
||
| 5 |
/// @notice Query if a contract implements an interface |
||
| 6 |
/// @param interfaceID The interface identifier, as specified in ERC-165 |
||
| 7 |
/// @dev Interface identification is specified in ERC-165. This function |
||
| 8 |
/// uses less than 30,000 gas. |
||
| 9 |
/// @return `true` if the contract implements `interfaceID` and |
||
| 10 |
/// `interfaceID` is not 0xffffffff, `false` otherwise |
||
| 11 |
function supportsInterface(bytes4 interfaceID) external view returns (bool); |
||
| 12 |
} |
||
| 13 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2; |
||
| 3 | |||
| 4 |
/// @dev Interface of the ERC20 standard as defined in the EIP. |
||
| 5 |
/// @dev This includes the optional name, symbol, and decimals metadata. |
||
| 6 |
interface IERC20 {
|
||
| 7 |
/// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). |
||
| 8 |
event Transfer(address indexed from, address indexed to, uint256 value); |
||
| 9 | |||
| 10 |
/// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` |
||
| 11 |
/// is the new allowance. |
||
| 12 |
event Approval(address indexed owner, address indexed spender, uint256 value); |
||
| 13 | |||
| 14 |
/// @notice Returns the amount of tokens in existence. |
||
| 15 |
function totalSupply() external view returns (uint256); |
||
| 16 | |||
| 17 |
/// @notice Returns the amount of tokens owned by `account`. |
||
| 18 |
function balanceOf(address account) external view returns (uint256); |
||
| 19 | |||
| 20 |
/// @notice Moves `amount` tokens from the caller's account to `to`. |
||
| 21 |
function transfer(address to, uint256 amount) external returns (bool); |
||
| 22 | |||
| 23 |
/// @notice Returns the remaining number of tokens that `spender` is allowed |
||
| 24 |
/// to spend on behalf of `owner` |
||
| 25 |
function allowance(address owner, address spender) external view returns (uint256); |
||
| 26 | |||
| 27 |
/// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. |
||
| 28 |
/// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 |
||
| 29 |
function approve(address spender, uint256 amount) external returns (bool); |
||
| 30 | |||
| 31 |
/// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. |
||
| 32 |
/// `amount` is then deducted from the caller's allowance. |
||
| 33 |
function transferFrom(address from, address to, uint256 amount) external returns (bool); |
||
| 34 | |||
| 35 |
/// @notice Returns the name of the token. |
||
| 36 |
function name() external view returns (string memory); |
||
| 37 | |||
| 38 |
/// @notice Returns the symbol of the token. |
||
| 39 |
function symbol() external view returns (string memory); |
||
| 40 | |||
| 41 |
/// @notice Returns the decimals places of the token. |
||
| 42 |
function decimals() external view returns (uint8); |
||
| 43 |
} |
||
| 44 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2; |
||
| 3 | |||
| 4 |
import "./IERC165.sol"; |
||
| 5 | |||
| 6 |
/// @title ERC-721 Non-Fungible Token Standard |
||
| 7 |
/// @dev See https://eips.ethereum.org/EIPS/eip-721 |
||
| 8 |
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd. |
||
| 9 |
interface IERC721 is IERC165 {
|
||
| 10 |
/// @dev This emits when ownership of any NFT changes by any mechanism. |
||
| 11 |
/// This event emits when NFTs are created (`from` == 0) and destroyed |
||
| 12 |
/// (`to` == 0). Exception: during contract creation, any number of NFTs |
||
| 13 |
/// may be created and assigned without emitting Transfer. At the time of |
||
| 14 |
/// any transfer, the approved address for that NFT (if any) is reset to none. |
||
| 15 |
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); |
||
| 16 | |||
| 17 |
/// @dev This emits when the approved address for an NFT is changed or |
||
| 18 |
/// reaffirmed. The zero address indicates there is no approved address. |
||
| 19 |
/// When a Transfer event emits, this also indicates that the approved |
||
| 20 |
/// address for that NFT (if any) is reset to none. |
||
| 21 |
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); |
||
| 22 | |||
| 23 |
/// @dev This emits when an operator is enabled or disabled for an owner. |
||
| 24 |
/// The operator can manage all NFTs of the owner. |
||
| 25 |
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); |
||
| 26 | |||
| 27 |
/// @notice Count all NFTs assigned to an owner |
||
| 28 |
/// @dev NFTs assigned to the zero address are considered invalid, and this |
||
| 29 |
/// function throws for queries about the zero address. |
||
| 30 |
/// @param _owner An address for whom to query the balance |
||
| 31 |
/// @return The number of NFTs owned by `_owner`, possibly zero |
||
| 32 |
function balanceOf(address _owner) external view returns (uint256); |
||
| 33 | |||
| 34 |
/// @notice Find the owner of an NFT |
||
| 35 |
/// @dev NFTs assigned to zero address are considered invalid, and queries |
||
| 36 |
/// about them do throw. |
||
| 37 |
/// @param _tokenId The identifier for an NFT |
||
| 38 |
/// @return The address of the owner of the NFT |
||
| 39 |
function ownerOf(uint256 _tokenId) external view returns (address); |
||
| 40 | |||
| 41 |
/// @notice Transfers the ownership of an NFT from one address to another address |
||
| 42 |
/// @dev Throws unless `msg.sender` is the current owner, an authorized |
||
| 43 |
/// operator, or the approved address for this NFT. Throws if `_from` is |
||
| 44 |
/// not the current owner. Throws if `_to` is the zero address. Throws if |
||
| 45 |
/// `_tokenId` is not a valid NFT. When transfer is complete, this function |
||
| 46 |
/// checks if `_to` is a smart contract (code size > 0). If so, it calls |
||
| 47 |
/// `onERC721Received` on `_to` and throws if the return value is not |
||
| 48 |
/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
|
||
| 49 |
/// @param _from The current owner of the NFT |
||
| 50 |
/// @param _to The new owner |
||
| 51 |
/// @param _tokenId The NFT to transfer |
||
| 52 |
/// @param data Additional data with no specified format, sent in call to `_to` |
||
| 53 |
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; |
||
| 54 | |||
| 55 |
/// @notice Transfers the ownership of an NFT from one address to another address |
||
| 56 |
/// @dev This works identically to the other function with an extra data parameter, |
||
| 57 |
/// except this function just sets data to "". |
||
| 58 |
/// @param _from The current owner of the NFT |
||
| 59 |
/// @param _to The new owner |
||
| 60 |
/// @param _tokenId The NFT to transfer |
||
| 61 |
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; |
||
| 62 | |||
| 63 |
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE |
||
| 64 |
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE |
||
| 65 |
/// THEY MAY BE PERMANENTLY LOST |
||
| 66 |
/// @dev Throws unless `msg.sender` is the current owner, an authorized |
||
| 67 |
/// operator, or the approved address for this NFT. Throws if `_from` is |
||
| 68 |
/// not the current owner. Throws if `_to` is the zero address. Throws if |
||
| 69 |
/// `_tokenId` is not a valid NFT. |
||
| 70 |
/// @param _from The current owner of the NFT |
||
| 71 |
/// @param _to The new owner |
||
| 72 |
/// @param _tokenId The NFT to transfer |
||
| 73 |
function transferFrom(address _from, address _to, uint256 _tokenId) external payable; |
||
| 74 | |||
| 75 |
/// @notice Change or reaffirm the approved address for an NFT |
||
| 76 |
/// @dev The zero address indicates there is no approved address. |
||
| 77 |
/// Throws unless `msg.sender` is the current NFT owner, or an authorized |
||
| 78 |
/// operator of the current owner. |
||
| 79 |
/// @param _approved The new approved NFT controller |
||
| 80 |
/// @param _tokenId The NFT to approve |
||
| 81 |
function approve(address _approved, uint256 _tokenId) external payable; |
||
| 82 | |||
| 83 |
/// @notice Enable or disable approval for a third party ("operator") to manage
|
||
| 84 |
/// all of `msg.sender`'s assets |
||
| 85 |
/// @dev Emits the ApprovalForAll event. The contract MUST allow |
||
| 86 |
/// multiple operators per owner. |
||
| 87 |
/// @param _operator Address to add to the set of authorized operators |
||
| 88 |
/// @param _approved True if the operator is approved, false to revoke approval |
||
| 89 |
function setApprovalForAll(address _operator, bool _approved) external; |
||
| 90 | |||
| 91 |
/// @notice Get the approved address for a single NFT |
||
| 92 |
/// @dev Throws if `_tokenId` is not a valid NFT. |
||
| 93 |
/// @param _tokenId The NFT to find the approved address for |
||
| 94 |
/// @return The approved address for this NFT, or the zero address if there is none |
||
| 95 |
function getApproved(uint256 _tokenId) external view returns (address); |
||
| 96 | |||
| 97 |
/// @notice Query if an address is an authorized operator for another address |
||
| 98 |
/// @param _owner The address that owns the NFTs |
||
| 99 |
/// @param _operator The address that acts on behalf of the owner |
||
| 100 |
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise |
||
| 101 |
function isApprovedForAll(address _owner, address _operator) external view returns (bool); |
||
| 102 |
} |
||
| 103 | |||
| 104 |
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. |
||
| 105 |
interface IERC721TokenReceiver {
|
||
| 106 |
/// @notice Handle the receipt of an NFT |
||
| 107 |
/// @dev The ERC721 smart contract calls this function on the recipient |
||
| 108 |
/// after a `transfer`. This function MAY throw to revert and reject the |
||
| 109 |
/// transfer. Return of other than the magic value MUST result in the |
||
| 110 |
/// transaction being reverted. |
||
| 111 |
/// Note: the contract address is always the message sender. |
||
| 112 |
/// @param _operator The address which called `safeTransferFrom` function |
||
| 113 |
/// @param _from The address which previously owned the token |
||
| 114 |
/// @param _tokenId The NFT identifier which is being transferred |
||
| 115 |
/// @param _data Additional data with no specified format |
||
| 116 |
/// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
|
||
| 117 |
/// unless throwing |
||
| 118 |
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) |
||
| 119 |
external |
||
| 120 |
returns (bytes4); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension |
||
| 124 |
/// @dev See https://eips.ethereum.org/EIPS/eip-721 |
||
| 125 |
/// Note: the ERC-165 identifier for this interface is 0x5b5e139f. |
||
| 126 |
interface IERC721Metadata is IERC721 {
|
||
| 127 |
/// @notice A descriptive name for a collection of NFTs in this contract |
||
| 128 |
function name() external view returns (string memory _name); |
||
| 129 | |||
| 130 |
/// @notice An abbreviated name for NFTs in this contract |
||
| 131 |
function symbol() external view returns (string memory _symbol); |
||
| 132 | |||
| 133 |
/// @notice A distinct Uniform Resource Identifier (URI) for a given asset. |
||
| 134 |
/// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC |
||
| 135 |
/// 3986. The URI may point to a JSON file that conforms to the "ERC721 |
||
| 136 |
/// Metadata JSON Schema". |
||
| 137 |
function tokenURI(uint256 _tokenId) external view returns (string memory); |
||
| 138 |
} |
||
| 139 | |||
| 140 |
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension |
||
| 141 |
/// @dev See https://eips.ethereum.org/EIPS/eip-721 |
||
| 142 |
/// Note: the ERC-165 identifier for this interface is 0x780e9d63. |
||
| 143 |
interface IERC721Enumerable is IERC721 {
|
||
| 144 |
/// @notice Count NFTs tracked by this contract |
||
| 145 |
/// @return A count of valid NFTs tracked by this contract, where each one of |
||
| 146 |
/// them has an assigned and queryable owner not equal to the zero address |
||
| 147 |
function totalSupply() external view returns (uint256); |
||
| 148 | |||
| 149 |
/// @notice Enumerate valid NFTs |
||
| 150 |
/// @dev Throws if `_index` >= `totalSupply()`. |
||
| 151 |
/// @param _index A counter less than `totalSupply()` |
||
| 152 |
/// @return The token identifier for the `_index`th NFT, |
||
| 153 |
/// (sort order not specified) |
||
| 154 |
function tokenByIndex(uint256 _index) external view returns (uint256); |
||
| 155 | |||
| 156 |
/// @notice Enumerate NFTs assigned to an owner |
||
| 157 |
/// @dev Throws if `_index` >= `balanceOf(_owner)` or if |
||
| 158 |
/// `_owner` is the zero address, representing invalid NFTs. |
||
| 159 |
/// @param _owner An address where we are interested in NFTs owned by them |
||
| 160 |
/// @param _index A counter less than `balanceOf(_owner)` |
||
| 161 |
/// @return The token identifier for the `_index`th NFT assigned to `_owner`, |
||
| 162 |
/// (sort order not specified) |
||
| 163 |
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); |
||
| 164 |
} |
||
| 165 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
pragma experimental ABIEncoderV2; |
||
| 5 | |||
| 6 |
interface IMulticall3 {
|
||
| 7 |
struct Call {
|
||
| 8 |
address target; |
||
| 9 |
bytes callData; |
||
| 10 |
} |
||
| 11 | |||
| 12 |
struct Call3 {
|
||
| 13 |
address target; |
||
| 14 |
bool allowFailure; |
||
| 15 |
bytes callData; |
||
| 16 |
} |
||
| 17 | |||
| 18 |
struct Call3Value {
|
||
| 19 |
address target; |
||
| 20 |
bool allowFailure; |
||
| 21 |
uint256 value; |
||
| 22 |
bytes callData; |
||
| 23 |
} |
||
| 24 | |||
| 25 |
struct Result {
|
||
| 26 |
bool success; |
||
| 27 |
bytes returnData; |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function aggregate(Call[] calldata calls) |
||
| 31 |
external |
||
| 32 |
payable |
||
| 33 |
returns (uint256 blockNumber, bytes[] memory returnData); |
||
| 34 | |||
| 35 |
function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); |
||
| 36 | |||
| 37 |
function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); |
||
| 38 | |||
| 39 |
function blockAndAggregate(Call[] calldata calls) |
||
| 40 |
external |
||
| 41 |
payable |
||
| 42 |
returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); |
||
| 43 | |||
| 44 |
function getBasefee() external view returns (uint256 basefee); |
||
| 45 | |||
| 46 |
function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); |
||
| 47 | |||
| 48 |
function getBlockNumber() external view returns (uint256 blockNumber); |
||
| 49 | |||
| 50 |
function getChainId() external view returns (uint256 chainid); |
||
| 51 | |||
| 52 |
function getCurrentBlockCoinbase() external view returns (address coinbase); |
||
| 53 | |||
| 54 |
function getCurrentBlockDifficulty() external view returns (uint256 difficulty); |
||
| 55 | |||
| 56 |
function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); |
||
| 57 | |||
| 58 |
function getCurrentBlockTimestamp() external view returns (uint256 timestamp); |
||
| 59 | |||
| 60 |
function getEthBalance(address addr) external view returns (uint256 balance); |
||
| 61 | |||
| 62 |
function getLastBlockHash() external view returns (bytes32 blockHash); |
||
| 63 | |||
| 64 |
function tryAggregate(bool requireSuccess, Call[] calldata calls) |
||
| 65 |
external |
||
| 66 |
payable |
||
| 67 |
returns (Result[] memory returnData); |
||
| 68 | |||
| 69 |
function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) |
||
| 70 |
external |
||
| 71 |
payable |
||
| 72 |
returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); |
||
| 73 |
} |
||
| 74 |
| Lines covered: | 0 / 63 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
import {IERC20} from "../interfaces/IERC20.sol";
|
||
| 5 | |||
| 6 |
/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. |
||
| 7 |
/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol |
||
| 8 |
contract MockERC20 is IERC20 {
|
||
| 9 |
/*////////////////////////////////////////////////////////////// |
||
| 10 |
METADATA STORAGE |
||
| 11 |
//////////////////////////////////////////////////////////////*/ |
||
| 12 | |||
| 13 |
string internal _name; |
||
| 14 | |||
| 15 |
string internal _symbol; |
||
| 16 | |||
| 17 |
uint8 internal _decimals; |
||
| 18 | |||
| 19 |
function name() external view override returns (string memory) {
|
||
| 20 |
return _name; |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function symbol() external view override returns (string memory) {
|
||
| 24 |
return _symbol; |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function decimals() external view override returns (uint8) {
|
||
| 28 |
return _decimals; |
||
| 29 |
} |
||
| 30 | |||
| 31 |
/*////////////////////////////////////////////////////////////// |
||
| 32 |
ERC20 STORAGE |
||
| 33 |
//////////////////////////////////////////////////////////////*/ |
||
| 34 | |||
| 35 |
uint256 internal _totalSupply; |
||
| 36 | |||
| 37 |
mapping(address => uint256) internal _balanceOf; |
||
| 38 | |||
| 39 |
mapping(address => mapping(address => uint256)) internal _allowance; |
||
| 40 | |||
| 41 |
function totalSupply() external view override returns (uint256) {
|
||
| 42 |
return _totalSupply; |
||
| 43 |
} |
||
| 44 | |||
| 45 |
function balanceOf(address owner) external view override returns (uint256) {
|
||
| 46 |
return _balanceOf[owner]; |
||
| 47 |
} |
||
| 48 | |||
| 49 |
function allowance(address owner, address spender) external view override returns (uint256) {
|
||
| 50 |
return _allowance[owner][spender]; |
||
| 51 |
} |
||
| 52 | |||
| 53 |
/*////////////////////////////////////////////////////////////// |
||
| 54 |
EIP-2612 STORAGE |
||
| 55 |
//////////////////////////////////////////////////////////////*/ |
||
| 56 | |||
| 57 |
uint256 internal INITIAL_CHAIN_ID; |
||
| 58 | |||
| 59 |
bytes32 internal INITIAL_DOMAIN_SEPARATOR; |
||
| 60 | |||
| 61 |
mapping(address => uint256) public nonces; |
||
| 62 | |||
| 63 |
/*////////////////////////////////////////////////////////////// |
||
| 64 |
INITIALIZE |
||
| 65 |
//////////////////////////////////////////////////////////////*/ |
||
| 66 | |||
| 67 |
/// @dev A bool to track whether the contract has been initialized. |
||
| 68 |
bool private initialized; |
||
| 69 | |||
| 70 |
/// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and |
||
| 71 |
/// syntaxes, we add an initialization function that can be called only once. |
||
| 72 |
function initialize(string memory name_, string memory symbol_, uint8 decimals_) public {
|
||
| 73 |
require(!initialized, "ALREADY_INITIALIZED"); |
||
| 74 | |||
| 75 |
_name = name_; |
||
| 76 |
_symbol = symbol_; |
||
| 77 |
_decimals = decimals_; |
||
| 78 | |||
| 79 |
INITIAL_CHAIN_ID = _pureChainId(); |
||
| 80 |
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); |
||
| 81 | |||
| 82 |
initialized = true; |
||
| 83 |
} |
||
| 84 | |||
| 85 |
/*////////////////////////////////////////////////////////////// |
||
| 86 |
ERC20 LOGIC |
||
| 87 |
//////////////////////////////////////////////////////////////*/ |
||
| 88 | |||
| 89 |
function approve(address spender, uint256 amount) public virtual override returns (bool) {
|
||
| 90 |
_allowance[msg.sender][spender] = amount; |
||
| 91 | |||
| 92 |
emit Approval(msg.sender, spender, amount); |
||
| 93 | |||
| 94 |
return true; |
||
| 95 |
} |
||
| 96 | |||
| 97 |
function transfer(address to, uint256 amount) public virtual override returns (bool) {
|
||
| 98 |
_balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount); |
||
| 99 |
_balanceOf[to] = _add(_balanceOf[to], amount); |
||
| 100 | |||
| 101 |
emit Transfer(msg.sender, to, amount); |
||
| 102 | |||
| 103 |
return true; |
||
| 104 |
} |
||
| 105 | |||
| 106 |
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
|
||
| 107 |
uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals. |
||
| 108 | |||
| 109 |
if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount); |
||
| 110 | |||
| 111 |
_balanceOf[from] = _sub(_balanceOf[from], amount); |
||
| 112 |
_balanceOf[to] = _add(_balanceOf[to], amount); |
||
| 113 | |||
| 114 |
emit Transfer(from, to, amount); |
||
| 115 | |||
| 116 |
return true; |
||
| 117 |
} |
||
| 118 | |||
| 119 |
/*////////////////////////////////////////////////////////////// |
||
| 120 |
EIP-2612 LOGIC |
||
| 121 |
//////////////////////////////////////////////////////////////*/ |
||
| 122 | |||
| 123 |
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) |
||
| 124 |
public |
||
| 125 |
virtual |
||
| 126 |
{
|
||
| 127 |
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); |
||
| 128 | |||
| 129 |
address recoveredAddress = ecrecover( |
||
| 130 |
keccak256( |
||
| 131 |
abi.encodePacked( |
||
| 132 |
"\x19\x01", |
||
| 133 |
DOMAIN_SEPARATOR(), |
||
| 134 |
keccak256( |
||
| 135 |
abi.encode( |
||
| 136 |
keccak256( |
||
| 137 |
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" |
||
| 138 |
), |
||
| 139 |
owner, |
||
| 140 |
spender, |
||
| 141 |
value, |
||
| 142 |
nonces[owner]++, |
||
| 143 |
deadline |
||
| 144 |
) |
||
| 145 |
) |
||
| 146 |
) |
||
| 147 |
), |
||
| 148 |
v, |
||
| 149 |
r, |
||
| 150 |
s |
||
| 151 |
); |
||
| 152 | |||
| 153 |
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); |
||
| 154 | |||
| 155 |
_allowance[recoveredAddress][spender] = value; |
||
| 156 | |||
| 157 |
emit Approval(owner, spender, value); |
||
| 158 |
} |
||
| 159 | |||
| 160 |
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
|
||
| 161 |
return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); |
||
| 162 |
} |
||
| 163 | |||
| 164 |
function computeDomainSeparator() internal view virtual returns (bytes32) {
|
||
| 165 |
return keccak256( |
||
| 166 |
abi.encode( |
||
| 167 |
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
|
||
| 168 |
keccak256(bytes(_name)), |
||
| 169 |
keccak256("1"),
|
||
| 170 |
_pureChainId(), |
||
| 171 |
address(this) |
||
| 172 |
) |
||
| 173 |
); |
||
| 174 |
} |
||
| 175 | |||
| 176 |
/*////////////////////////////////////////////////////////////// |
||
| 177 |
INTERNAL MINT/BURN LOGIC |
||
| 178 |
//////////////////////////////////////////////////////////////*/ |
||
| 179 | |||
| 180 |
function _mint(address to, uint256 amount) internal virtual {
|
||
| 181 |
_totalSupply = _add(_totalSupply, amount); |
||
| 182 |
_balanceOf[to] = _add(_balanceOf[to], amount); |
||
| 183 | |||
| 184 |
emit Transfer(address(0), to, amount); |
||
| 185 |
} |
||
| 186 | |||
| 187 |
function _burn(address from, uint256 amount) internal virtual {
|
||
| 188 |
_balanceOf[from] = _sub(_balanceOf[from], amount); |
||
| 189 |
_totalSupply = _sub(_totalSupply, amount); |
||
| 190 | |||
| 191 |
emit Transfer(from, address(0), amount); |
||
| 192 |
} |
||
| 193 | |||
| 194 |
/*////////////////////////////////////////////////////////////// |
||
| 195 |
INTERNAL SAFE MATH LOGIC |
||
| 196 |
//////////////////////////////////////////////////////////////*/ |
||
| 197 | |||
| 198 |
function _add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||
| 199 |
uint256 c = a + b; |
||
| 200 |
require(c >= a, "ERC20: addition overflow"); |
||
| 201 |
return c; |
||
| 202 |
} |
||
| 203 | |||
| 204 |
function _sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||
| 205 |
require(a >= b, "ERC20: subtraction underflow"); |
||
| 206 |
return a - b; |
||
| 207 |
} |
||
| 208 | |||
| 209 |
/*////////////////////////////////////////////////////////////// |
||
| 210 |
HELPERS |
||
| 211 |
//////////////////////////////////////////////////////////////*/ |
||
| 212 | |||
| 213 |
// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no |
||
| 214 |
// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We |
||
| 215 |
// can't simply access the chain ID in a normal view or pure function because the solc View Pure |
||
| 216 |
// Checker changed `chainid` from pure to view in 0.8.0. |
||
| 217 |
function _viewChainId() private view returns (uint256 chainId) {
|
||
| 218 |
// Assembly required since `block.chainid` was introduced in 0.8.0. |
||
| 219 |
assembly {
|
||
| 220 |
chainId := chainid() |
||
| 221 |
} |
||
| 222 | |||
| 223 |
address(this); // Silence warnings in older Solc versions. |
||
| 224 |
} |
||
| 225 | |||
| 226 |
function _pureChainId() private pure returns (uint256 chainId) {
|
||
| 227 |
function() internal view returns (uint256) fnIn = _viewChainId; |
||
| 228 |
function() internal pure returns (uint256) pureChainId; |
||
| 229 |
assembly {
|
||
| 230 |
pureChainId := fnIn |
||
| 231 |
} |
||
| 232 |
chainId = pureChainId(); |
||
| 233 |
} |
||
| 234 |
} |
||
| 235 |
| Lines covered: | 0 / 45 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol";
|
||
| 5 | |||
| 6 |
/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. |
||
| 7 |
/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol |
||
| 8 |
contract MockERC721 is IERC721Metadata {
|
||
| 9 |
/*////////////////////////////////////////////////////////////// |
||
| 10 |
METADATA STORAGE/LOGIC |
||
| 11 |
//////////////////////////////////////////////////////////////*/ |
||
| 12 | |||
| 13 |
string internal _name; |
||
| 14 | |||
| 15 |
string internal _symbol; |
||
| 16 | |||
| 17 |
function name() external view override returns (string memory) {
|
||
| 18 |
return _name; |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function symbol() external view override returns (string memory) {
|
||
| 22 |
return _symbol; |
||
| 23 |
} |
||
| 24 | |||
| 25 |
function tokenURI(uint256 id) public view virtual override returns (string memory) {}
|
||
| 26 | |||
| 27 |
/*////////////////////////////////////////////////////////////// |
||
| 28 |
ERC721 BALANCE/OWNER STORAGE |
||
| 29 |
//////////////////////////////////////////////////////////////*/ |
||
| 30 | |||
| 31 |
mapping(uint256 => address) internal _ownerOf; |
||
| 32 | |||
| 33 |
mapping(address => uint256) internal _balanceOf; |
||
| 34 | |||
| 35 |
function ownerOf(uint256 id) public view virtual override returns (address owner) {
|
||
| 36 |
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function balanceOf(address owner) public view virtual override returns (uint256) {
|
||
| 40 |
require(owner != address(0), "ZERO_ADDRESS"); |
||
| 41 | |||
| 42 |
return _balanceOf[owner]; |
||
| 43 |
} |
||
| 44 | |||
| 45 |
/*////////////////////////////////////////////////////////////// |
||
| 46 |
ERC721 APPROVAL STORAGE |
||
| 47 |
//////////////////////////////////////////////////////////////*/ |
||
| 48 | |||
| 49 |
mapping(uint256 => address) internal _getApproved; |
||
| 50 | |||
| 51 |
mapping(address => mapping(address => bool)) internal _isApprovedForAll; |
||
| 52 | |||
| 53 |
function getApproved(uint256 id) public view virtual override returns (address) {
|
||
| 54 |
return _getApproved[id]; |
||
| 55 |
} |
||
| 56 | |||
| 57 |
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
|
||
| 58 |
return _isApprovedForAll[owner][operator]; |
||
| 59 |
} |
||
| 60 | |||
| 61 |
/*////////////////////////////////////////////////////////////// |
||
| 62 |
INITIALIZE |
||
| 63 |
//////////////////////////////////////////////////////////////*/ |
||
| 64 | |||
| 65 |
/// @dev A bool to track whether the contract has been initialized. |
||
| 66 |
bool private initialized; |
||
| 67 | |||
| 68 |
/// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and |
||
| 69 |
/// syntaxes, we add an initialization function that can be called only once. |
||
| 70 |
function initialize(string memory name_, string memory symbol_) public {
|
||
| 71 |
require(!initialized, "ALREADY_INITIALIZED"); |
||
| 72 | |||
| 73 |
_name = name_; |
||
| 74 |
_symbol = symbol_; |
||
| 75 | |||
| 76 |
initialized = true; |
||
| 77 |
} |
||
| 78 | |||
| 79 |
/*////////////////////////////////////////////////////////////// |
||
| 80 |
ERC721 LOGIC |
||
| 81 |
//////////////////////////////////////////////////////////////*/ |
||
| 82 | |||
| 83 |
function approve(address spender, uint256 id) public payable virtual override {
|
||
| 84 |
address owner = _ownerOf[id]; |
||
| 85 | |||
| 86 |
require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); |
||
| 87 | |||
| 88 |
_getApproved[id] = spender; |
||
| 89 | |||
| 90 |
emit Approval(owner, spender, id); |
||
| 91 |
} |
||
| 92 | |||
| 93 |
function setApprovalForAll(address operator, bool approved) public virtual override {
|
||
| 94 |
_isApprovedForAll[msg.sender][operator] = approved; |
||
| 95 | |||
| 96 |
emit ApprovalForAll(msg.sender, operator, approved); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function transferFrom(address from, address to, uint256 id) public payable virtual override {
|
||
| 100 |
require(from == _ownerOf[id], "WRONG_FROM"); |
||
| 101 | |||
| 102 |
require(to != address(0), "INVALID_RECIPIENT"); |
||
| 103 | |||
| 104 |
require( |
||
| 105 |
msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id], |
||
| 106 |
"NOT_AUTHORIZED" |
||
| 107 |
); |
||
| 108 | |||
| 109 |
// Underflow of the sender's balance is impossible because we check for |
||
| 110 |
// ownership above and the recipient's balance can't realistically overflow. |
||
| 111 |
_balanceOf[from]--; |
||
| 112 | |||
| 113 |
_balanceOf[to]++; |
||
| 114 | |||
| 115 |
_ownerOf[id] = to; |
||
| 116 | |||
| 117 |
delete _getApproved[id]; |
||
| 118 | |||
| 119 |
emit Transfer(from, to, id); |
||
| 120 |
} |
||
| 121 | |||
| 122 |
function safeTransferFrom(address from, address to, uint256 id) public payable virtual override {
|
||
| 123 |
transferFrom(from, to, id); |
||
| 124 | |||
| 125 |
require( |
||
| 126 |
!_isContract(to) |
||
| 127 |
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") |
||
| 128 |
== IERC721TokenReceiver.onERC721Received.selector, |
||
| 129 |
"UNSAFE_RECIPIENT" |
||
| 130 |
); |
||
| 131 |
} |
||
| 132 | |||
| 133 |
function safeTransferFrom(address from, address to, uint256 id, bytes memory data) |
||
| 134 |
public |
||
| 135 |
payable |
||
| 136 |
virtual |
||
| 137 |
override |
||
| 138 |
{
|
||
| 139 |
transferFrom(from, to, id); |
||
| 140 | |||
| 141 |
require( |
||
| 142 |
!_isContract(to) |
||
| 143 |
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) |
||
| 144 |
== IERC721TokenReceiver.onERC721Received.selector, |
||
| 145 |
"UNSAFE_RECIPIENT" |
||
| 146 |
); |
||
| 147 |
} |
||
| 148 | |||
| 149 |
/*////////////////////////////////////////////////////////////// |
||
| 150 |
ERC165 LOGIC |
||
| 151 |
//////////////////////////////////////////////////////////////*/ |
||
| 152 | |||
| 153 |
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
||
| 154 |
return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 |
||
| 155 |
|| interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 |
||
| 156 |
|| interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata |
||
| 157 |
} |
||
| 158 | |||
| 159 |
/*////////////////////////////////////////////////////////////// |
||
| 160 |
INTERNAL MINT/BURN LOGIC |
||
| 161 |
//////////////////////////////////////////////////////////////*/ |
||
| 162 | |||
| 163 |
function _mint(address to, uint256 id) internal virtual {
|
||
| 164 |
require(to != address(0), "INVALID_RECIPIENT"); |
||
| 165 | |||
| 166 |
require(_ownerOf[id] == address(0), "ALREADY_MINTED"); |
||
| 167 | |||
| 168 |
// Counter overflow is incredibly unrealistic. |
||
| 169 | |||
| 170 |
_balanceOf[to]++; |
||
| 171 | |||
| 172 |
_ownerOf[id] = to; |
||
| 173 | |||
| 174 |
emit Transfer(address(0), to, id); |
||
| 175 |
} |
||
| 176 | |||
| 177 |
function _burn(uint256 id) internal virtual {
|
||
| 178 |
address owner = _ownerOf[id]; |
||
| 179 | |||
| 180 |
require(owner != address(0), "NOT_MINTED"); |
||
| 181 | |||
| 182 |
_balanceOf[owner]--; |
||
| 183 | |||
| 184 |
delete _ownerOf[id]; |
||
| 185 | |||
| 186 |
delete _getApproved[id]; |
||
| 187 | |||
| 188 |
emit Transfer(owner, address(0), id); |
||
| 189 |
} |
||
| 190 | |||
| 191 |
/*////////////////////////////////////////////////////////////// |
||
| 192 |
INTERNAL SAFE MINT LOGIC |
||
| 193 |
//////////////////////////////////////////////////////////////*/ |
||
| 194 | |||
| 195 |
function _safeMint(address to, uint256 id) internal virtual {
|
||
| 196 |
_mint(to, id); |
||
| 197 | |||
| 198 |
require( |
||
| 199 |
!_isContract(to) |
||
| 200 |
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") |
||
| 201 |
== IERC721TokenReceiver.onERC721Received.selector, |
||
| 202 |
"UNSAFE_RECIPIENT" |
||
| 203 |
); |
||
| 204 |
} |
||
| 205 | |||
| 206 |
function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
|
||
| 207 |
_mint(to, id); |
||
| 208 | |||
| 209 |
require( |
||
| 210 |
!_isContract(to) |
||
| 211 |
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) |
||
| 212 |
== IERC721TokenReceiver.onERC721Received.selector, |
||
| 213 |
"UNSAFE_RECIPIENT" |
||
| 214 |
); |
||
| 215 |
} |
||
| 216 | |||
| 217 |
/*////////////////////////////////////////////////////////////// |
||
| 218 |
HELPERS |
||
| 219 |
//////////////////////////////////////////////////////////////*/ |
||
| 220 | |||
| 221 |
function _isContract(address _addr) private view returns (bool) {
|
||
| 222 |
uint256 codeLength; |
||
| 223 | |||
| 224 |
// Assembly required for versions < 0.8.0 to check extcodesize. |
||
| 225 |
assembly {
|
||
| 226 |
codeLength := extcodesize(_addr) |
||
| 227 |
} |
||
| 228 | |||
| 229 |
return codeLength > 0; |
||
| 230 |
} |
||
| 231 |
} |
||
| 232 |
| Lines covered: | 0 / 1 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity >=0.6.2 <0.9.0; |
||
| 3 | |||
| 4 |
/// @author philogy <https://github.com/philogy> |
||
| 5 |
/// @dev Code generated automatically by script. |
||
| 6 |
library safeconsole {
|
||
| 7 |
uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67; |
||
| 8 | |||
| 9 |
// Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374) |
||
| 10 |
// for the view-to-pure log trick. |
||
| 11 |
function _sendLogPayload(uint256 offset, uint256 size) private pure {
|
||
| 12 |
function(uint256, uint256) internal view fnIn = _sendLogPayloadView; |
||
| 13 |
function(uint256, uint256) internal pure pureSendLogPayload; |
||
| 14 |
/// @solidity memory-safe-assembly |
||
| 15 |
assembly {
|
||
| 16 |
pureSendLogPayload := fnIn |
||
| 17 |
} |
||
| 18 |
pureSendLogPayload(offset, size); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function _sendLogPayloadView(uint256 offset, uint256 size) private view {
|
||
| 22 |
/// @solidity memory-safe-assembly |
||
| 23 |
assembly {
|
||
| 24 |
pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) |
||
| 25 |
} |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
|
||
| 29 |
function(uint256, uint256, uint256) internal view fnIn = _memcopyView; |
||
| 30 |
function(uint256, uint256, uint256) internal pure pureMemcopy; |
||
| 31 |
/// @solidity memory-safe-assembly |
||
| 32 |
assembly {
|
||
| 33 |
pureMemcopy := fnIn |
||
| 34 |
} |
||
| 35 |
pureMemcopy(fromOffset, toOffset, length); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
|
||
| 39 |
/// @solidity memory-safe-assembly |
||
| 40 |
assembly {
|
||
| 41 |
pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) |
||
| 42 |
} |
||
| 43 |
} |
||
| 44 | |||
| 45 |
function logMemory(uint256 offset, uint256 length) internal pure {
|
||
| 46 |
if (offset >= 0x60) {
|
||
| 47 |
// Sufficient memory before slice to prepare call header. |
||
| 48 |
bytes32 m0; |
||
| 49 |
bytes32 m1; |
||
| 50 |
bytes32 m2; |
||
| 51 |
/// @solidity memory-safe-assembly |
||
| 52 |
assembly {
|
||
| 53 |
m0 := mload(sub(offset, 0x60)) |
||
| 54 |
m1 := mload(sub(offset, 0x40)) |
||
| 55 |
m2 := mload(sub(offset, 0x20)) |
||
| 56 |
// Selector of `log(bytes)`. |
||
| 57 |
mstore(sub(offset, 0x60), 0x0be77f56) |
||
| 58 |
mstore(sub(offset, 0x40), 0x20) |
||
| 59 |
mstore(sub(offset, 0x20), length) |
||
| 60 |
} |
||
| 61 |
_sendLogPayload(offset - 0x44, length + 0x44); |
||
| 62 |
/// @solidity memory-safe-assembly |
||
| 63 |
assembly {
|
||
| 64 |
mstore(sub(offset, 0x60), m0) |
||
| 65 |
mstore(sub(offset, 0x40), m1) |
||
| 66 |
mstore(sub(offset, 0x20), m2) |
||
| 67 |
} |
||
| 68 |
} else {
|
||
| 69 |
// Insufficient space, so copy slice forward, add header and reverse. |
||
| 70 |
bytes32 m0; |
||
| 71 |
bytes32 m1; |
||
| 72 |
bytes32 m2; |
||
| 73 |
uint256 endOffset = offset + length; |
||
| 74 |
/// @solidity memory-safe-assembly |
||
| 75 |
assembly {
|
||
| 76 |
m0 := mload(add(endOffset, 0x00)) |
||
| 77 |
m1 := mload(add(endOffset, 0x20)) |
||
| 78 |
m2 := mload(add(endOffset, 0x40)) |
||
| 79 |
} |
||
| 80 |
_memcopy(offset, offset + 0x60, length); |
||
| 81 |
/// @solidity memory-safe-assembly |
||
| 82 |
assembly {
|
||
| 83 |
// Selector of `log(bytes)`. |
||
| 84 |
mstore(add(offset, 0x00), 0x0be77f56) |
||
| 85 |
mstore(add(offset, 0x20), 0x20) |
||
| 86 |
mstore(add(offset, 0x40), length) |
||
| 87 |
} |
||
| 88 |
_sendLogPayload(offset + 0x1c, length + 0x44); |
||
| 89 |
_memcopy(offset + 0x60, offset, length); |
||
| 90 |
/// @solidity memory-safe-assembly |
||
| 91 |
assembly {
|
||
| 92 |
mstore(add(endOffset, 0x00), m0) |
||
| 93 |
mstore(add(endOffset, 0x20), m1) |
||
| 94 |
mstore(add(endOffset, 0x40), m2) |
||
| 95 |
} |
||
| 96 |
} |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function log(address p0) internal pure {
|
||
| 100 |
bytes32 m0; |
||
| 101 |
bytes32 m1; |
||
| 102 |
/// @solidity memory-safe-assembly |
||
| 103 |
assembly {
|
||
| 104 |
m0 := mload(0x00) |
||
| 105 |
m1 := mload(0x20) |
||
| 106 |
// Selector of `log(address)`. |
||
| 107 |
mstore(0x00, 0x2c2ecbc2) |
||
| 108 |
mstore(0x20, p0) |
||
| 109 |
} |
||
| 110 |
_sendLogPayload(0x1c, 0x24); |
||
| 111 |
/// @solidity memory-safe-assembly |
||
| 112 |
assembly {
|
||
| 113 |
mstore(0x00, m0) |
||
| 114 |
mstore(0x20, m1) |
||
| 115 |
} |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function log(bool p0) internal pure {
|
||
| 119 |
bytes32 m0; |
||
| 120 |
bytes32 m1; |
||
| 121 |
/// @solidity memory-safe-assembly |
||
| 122 |
assembly {
|
||
| 123 |
m0 := mload(0x00) |
||
| 124 |
m1 := mload(0x20) |
||
| 125 |
// Selector of `log(bool)`. |
||
| 126 |
mstore(0x00, 0x32458eed) |
||
| 127 |
mstore(0x20, p0) |
||
| 128 |
} |
||
| 129 |
_sendLogPayload(0x1c, 0x24); |
||
| 130 |
/// @solidity memory-safe-assembly |
||
| 131 |
assembly {
|
||
| 132 |
mstore(0x00, m0) |
||
| 133 |
mstore(0x20, m1) |
||
| 134 |
} |
||
| 135 |
} |
||
| 136 | |||
| 137 |
function log(uint256 p0) internal pure {
|
||
| 138 |
bytes32 m0; |
||
| 139 |
bytes32 m1; |
||
| 140 |
/// @solidity memory-safe-assembly |
||
| 141 |
assembly {
|
||
| 142 |
m0 := mload(0x00) |
||
| 143 |
m1 := mload(0x20) |
||
| 144 |
// Selector of `log(uint256)`. |
||
| 145 |
mstore(0x00, 0xf82c50f1) |
||
| 146 |
mstore(0x20, p0) |
||
| 147 |
} |
||
| 148 |
_sendLogPayload(0x1c, 0x24); |
||
| 149 |
/// @solidity memory-safe-assembly |
||
| 150 |
assembly {
|
||
| 151 |
mstore(0x00, m0) |
||
| 152 |
mstore(0x20, m1) |
||
| 153 |
} |
||
| 154 |
} |
||
| 155 | |||
| 156 |
function log(bytes32 p0) internal pure {
|
||
| 157 |
bytes32 m0; |
||
| 158 |
bytes32 m1; |
||
| 159 |
bytes32 m2; |
||
| 160 |
bytes32 m3; |
||
| 161 |
/// @solidity memory-safe-assembly |
||
| 162 |
assembly {
|
||
| 163 |
function writeString(pos, w) {
|
||
| 164 |
let length := 0 |
||
| 165 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 166 |
mstore(pos, length) |
||
| 167 |
let shift := sub(256, shl(3, length)) |
||
| 168 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 169 |
} |
||
| 170 |
m0 := mload(0x00) |
||
| 171 |
m1 := mload(0x20) |
||
| 172 |
m2 := mload(0x40) |
||
| 173 |
m3 := mload(0x60) |
||
| 174 |
// Selector of `log(string)`. |
||
| 175 |
mstore(0x00, 0x41304fac) |
||
| 176 |
mstore(0x20, 0x20) |
||
| 177 |
writeString(0x40, p0) |
||
| 178 |
} |
||
| 179 |
_sendLogPayload(0x1c, 0x64); |
||
| 180 |
/// @solidity memory-safe-assembly |
||
| 181 |
assembly {
|
||
| 182 |
mstore(0x00, m0) |
||
| 183 |
mstore(0x20, m1) |
||
| 184 |
mstore(0x40, m2) |
||
| 185 |
mstore(0x60, m3) |
||
| 186 |
} |
||
| 187 |
} |
||
| 188 | |||
| 189 |
function log(address p0, address p1) internal pure {
|
||
| 190 |
bytes32 m0; |
||
| 191 |
bytes32 m1; |
||
| 192 |
bytes32 m2; |
||
| 193 |
/// @solidity memory-safe-assembly |
||
| 194 |
assembly {
|
||
| 195 |
m0 := mload(0x00) |
||
| 196 |
m1 := mload(0x20) |
||
| 197 |
m2 := mload(0x40) |
||
| 198 |
// Selector of `log(address,address)`. |
||
| 199 |
mstore(0x00, 0xdaf0d4aa) |
||
| 200 |
mstore(0x20, p0) |
||
| 201 |
mstore(0x40, p1) |
||
| 202 |
} |
||
| 203 |
_sendLogPayload(0x1c, 0x44); |
||
| 204 |
/// @solidity memory-safe-assembly |
||
| 205 |
assembly {
|
||
| 206 |
mstore(0x00, m0) |
||
| 207 |
mstore(0x20, m1) |
||
| 208 |
mstore(0x40, m2) |
||
| 209 |
} |
||
| 210 |
} |
||
| 211 | |||
| 212 |
function log(address p0, bool p1) internal pure {
|
||
| 213 |
bytes32 m0; |
||
| 214 |
bytes32 m1; |
||
| 215 |
bytes32 m2; |
||
| 216 |
/// @solidity memory-safe-assembly |
||
| 217 |
assembly {
|
||
| 218 |
m0 := mload(0x00) |
||
| 219 |
m1 := mload(0x20) |
||
| 220 |
m2 := mload(0x40) |
||
| 221 |
// Selector of `log(address,bool)`. |
||
| 222 |
mstore(0x00, 0x75b605d3) |
||
| 223 |
mstore(0x20, p0) |
||
| 224 |
mstore(0x40, p1) |
||
| 225 |
} |
||
| 226 |
_sendLogPayload(0x1c, 0x44); |
||
| 227 |
/// @solidity memory-safe-assembly |
||
| 228 |
assembly {
|
||
| 229 |
mstore(0x00, m0) |
||
| 230 |
mstore(0x20, m1) |
||
| 231 |
mstore(0x40, m2) |
||
| 232 |
} |
||
| 233 |
} |
||
| 234 | |||
| 235 |
function log(address p0, uint256 p1) internal pure {
|
||
| 236 |
bytes32 m0; |
||
| 237 |
bytes32 m1; |
||
| 238 |
bytes32 m2; |
||
| 239 |
/// @solidity memory-safe-assembly |
||
| 240 |
assembly {
|
||
| 241 |
m0 := mload(0x00) |
||
| 242 |
m1 := mload(0x20) |
||
| 243 |
m2 := mload(0x40) |
||
| 244 |
// Selector of `log(address,uint256)`. |
||
| 245 |
mstore(0x00, 0x8309e8a8) |
||
| 246 |
mstore(0x20, p0) |
||
| 247 |
mstore(0x40, p1) |
||
| 248 |
} |
||
| 249 |
_sendLogPayload(0x1c, 0x44); |
||
| 250 |
/// @solidity memory-safe-assembly |
||
| 251 |
assembly {
|
||
| 252 |
mstore(0x00, m0) |
||
| 253 |
mstore(0x20, m1) |
||
| 254 |
mstore(0x40, m2) |
||
| 255 |
} |
||
| 256 |
} |
||
| 257 | |||
| 258 |
function log(address p0, bytes32 p1) internal pure {
|
||
| 259 |
bytes32 m0; |
||
| 260 |
bytes32 m1; |
||
| 261 |
bytes32 m2; |
||
| 262 |
bytes32 m3; |
||
| 263 |
bytes32 m4; |
||
| 264 |
/// @solidity memory-safe-assembly |
||
| 265 |
assembly {
|
||
| 266 |
function writeString(pos, w) {
|
||
| 267 |
let length := 0 |
||
| 268 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 269 |
mstore(pos, length) |
||
| 270 |
let shift := sub(256, shl(3, length)) |
||
| 271 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 272 |
} |
||
| 273 |
m0 := mload(0x00) |
||
| 274 |
m1 := mload(0x20) |
||
| 275 |
m2 := mload(0x40) |
||
| 276 |
m3 := mload(0x60) |
||
| 277 |
m4 := mload(0x80) |
||
| 278 |
// Selector of `log(address,string)`. |
||
| 279 |
mstore(0x00, 0x759f86bb) |
||
| 280 |
mstore(0x20, p0) |
||
| 281 |
mstore(0x40, 0x40) |
||
| 282 |
writeString(0x60, p1) |
||
| 283 |
} |
||
| 284 |
_sendLogPayload(0x1c, 0x84); |
||
| 285 |
/// @solidity memory-safe-assembly |
||
| 286 |
assembly {
|
||
| 287 |
mstore(0x00, m0) |
||
| 288 |
mstore(0x20, m1) |
||
| 289 |
mstore(0x40, m2) |
||
| 290 |
mstore(0x60, m3) |
||
| 291 |
mstore(0x80, m4) |
||
| 292 |
} |
||
| 293 |
} |
||
| 294 | |||
| 295 |
function log(bool p0, address p1) internal pure {
|
||
| 296 |
bytes32 m0; |
||
| 297 |
bytes32 m1; |
||
| 298 |
bytes32 m2; |
||
| 299 |
/// @solidity memory-safe-assembly |
||
| 300 |
assembly {
|
||
| 301 |
m0 := mload(0x00) |
||
| 302 |
m1 := mload(0x20) |
||
| 303 |
m2 := mload(0x40) |
||
| 304 |
// Selector of `log(bool,address)`. |
||
| 305 |
mstore(0x00, 0x853c4849) |
||
| 306 |
mstore(0x20, p0) |
||
| 307 |
mstore(0x40, p1) |
||
| 308 |
} |
||
| 309 |
_sendLogPayload(0x1c, 0x44); |
||
| 310 |
/// @solidity memory-safe-assembly |
||
| 311 |
assembly {
|
||
| 312 |
mstore(0x00, m0) |
||
| 313 |
mstore(0x20, m1) |
||
| 314 |
mstore(0x40, m2) |
||
| 315 |
} |
||
| 316 |
} |
||
| 317 | |||
| 318 |
function log(bool p0, bool p1) internal pure {
|
||
| 319 |
bytes32 m0; |
||
| 320 |
bytes32 m1; |
||
| 321 |
bytes32 m2; |
||
| 322 |
/// @solidity memory-safe-assembly |
||
| 323 |
assembly {
|
||
| 324 |
m0 := mload(0x00) |
||
| 325 |
m1 := mload(0x20) |
||
| 326 |
m2 := mload(0x40) |
||
| 327 |
// Selector of `log(bool,bool)`. |
||
| 328 |
mstore(0x00, 0x2a110e83) |
||
| 329 |
mstore(0x20, p0) |
||
| 330 |
mstore(0x40, p1) |
||
| 331 |
} |
||
| 332 |
_sendLogPayload(0x1c, 0x44); |
||
| 333 |
/// @solidity memory-safe-assembly |
||
| 334 |
assembly {
|
||
| 335 |
mstore(0x00, m0) |
||
| 336 |
mstore(0x20, m1) |
||
| 337 |
mstore(0x40, m2) |
||
| 338 |
} |
||
| 339 |
} |
||
| 340 | |||
| 341 |
function log(bool p0, uint256 p1) internal pure {
|
||
| 342 |
bytes32 m0; |
||
| 343 |
bytes32 m1; |
||
| 344 |
bytes32 m2; |
||
| 345 |
/// @solidity memory-safe-assembly |
||
| 346 |
assembly {
|
||
| 347 |
m0 := mload(0x00) |
||
| 348 |
m1 := mload(0x20) |
||
| 349 |
m2 := mload(0x40) |
||
| 350 |
// Selector of `log(bool,uint256)`. |
||
| 351 |
mstore(0x00, 0x399174d3) |
||
| 352 |
mstore(0x20, p0) |
||
| 353 |
mstore(0x40, p1) |
||
| 354 |
} |
||
| 355 |
_sendLogPayload(0x1c, 0x44); |
||
| 356 |
/// @solidity memory-safe-assembly |
||
| 357 |
assembly {
|
||
| 358 |
mstore(0x00, m0) |
||
| 359 |
mstore(0x20, m1) |
||
| 360 |
mstore(0x40, m2) |
||
| 361 |
} |
||
| 362 |
} |
||
| 363 | |||
| 364 |
function log(bool p0, bytes32 p1) internal pure {
|
||
| 365 |
bytes32 m0; |
||
| 366 |
bytes32 m1; |
||
| 367 |
bytes32 m2; |
||
| 368 |
bytes32 m3; |
||
| 369 |
bytes32 m4; |
||
| 370 |
/// @solidity memory-safe-assembly |
||
| 371 |
assembly {
|
||
| 372 |
function writeString(pos, w) {
|
||
| 373 |
let length := 0 |
||
| 374 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 375 |
mstore(pos, length) |
||
| 376 |
let shift := sub(256, shl(3, length)) |
||
| 377 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 378 |
} |
||
| 379 |
m0 := mload(0x00) |
||
| 380 |
m1 := mload(0x20) |
||
| 381 |
m2 := mload(0x40) |
||
| 382 |
m3 := mload(0x60) |
||
| 383 |
m4 := mload(0x80) |
||
| 384 |
// Selector of `log(bool,string)`. |
||
| 385 |
mstore(0x00, 0x8feac525) |
||
| 386 |
mstore(0x20, p0) |
||
| 387 |
mstore(0x40, 0x40) |
||
| 388 |
writeString(0x60, p1) |
||
| 389 |
} |
||
| 390 |
_sendLogPayload(0x1c, 0x84); |
||
| 391 |
/// @solidity memory-safe-assembly |
||
| 392 |
assembly {
|
||
| 393 |
mstore(0x00, m0) |
||
| 394 |
mstore(0x20, m1) |
||
| 395 |
mstore(0x40, m2) |
||
| 396 |
mstore(0x60, m3) |
||
| 397 |
mstore(0x80, m4) |
||
| 398 |
} |
||
| 399 |
} |
||
| 400 | |||
| 401 |
function log(uint256 p0, address p1) internal pure {
|
||
| 402 |
bytes32 m0; |
||
| 403 |
bytes32 m1; |
||
| 404 |
bytes32 m2; |
||
| 405 |
/// @solidity memory-safe-assembly |
||
| 406 |
assembly {
|
||
| 407 |
m0 := mload(0x00) |
||
| 408 |
m1 := mload(0x20) |
||
| 409 |
m2 := mload(0x40) |
||
| 410 |
// Selector of `log(uint256,address)`. |
||
| 411 |
mstore(0x00, 0x69276c86) |
||
| 412 |
mstore(0x20, p0) |
||
| 413 |
mstore(0x40, p1) |
||
| 414 |
} |
||
| 415 |
_sendLogPayload(0x1c, 0x44); |
||
| 416 |
/// @solidity memory-safe-assembly |
||
| 417 |
assembly {
|
||
| 418 |
mstore(0x00, m0) |
||
| 419 |
mstore(0x20, m1) |
||
| 420 |
mstore(0x40, m2) |
||
| 421 |
} |
||
| 422 |
} |
||
| 423 | |||
| 424 |
function log(uint256 p0, bool p1) internal pure {
|
||
| 425 |
bytes32 m0; |
||
| 426 |
bytes32 m1; |
||
| 427 |
bytes32 m2; |
||
| 428 |
/// @solidity memory-safe-assembly |
||
| 429 |
assembly {
|
||
| 430 |
m0 := mload(0x00) |
||
| 431 |
m1 := mload(0x20) |
||
| 432 |
m2 := mload(0x40) |
||
| 433 |
// Selector of `log(uint256,bool)`. |
||
| 434 |
mstore(0x00, 0x1c9d7eb3) |
||
| 435 |
mstore(0x20, p0) |
||
| 436 |
mstore(0x40, p1) |
||
| 437 |
} |
||
| 438 |
_sendLogPayload(0x1c, 0x44); |
||
| 439 |
/// @solidity memory-safe-assembly |
||
| 440 |
assembly {
|
||
| 441 |
mstore(0x00, m0) |
||
| 442 |
mstore(0x20, m1) |
||
| 443 |
mstore(0x40, m2) |
||
| 444 |
} |
||
| 445 |
} |
||
| 446 | |||
| 447 |
function log(uint256 p0, uint256 p1) internal pure {
|
||
| 448 |
bytes32 m0; |
||
| 449 |
bytes32 m1; |
||
| 450 |
bytes32 m2; |
||
| 451 |
/// @solidity memory-safe-assembly |
||
| 452 |
assembly {
|
||
| 453 |
m0 := mload(0x00) |
||
| 454 |
m1 := mload(0x20) |
||
| 455 |
m2 := mload(0x40) |
||
| 456 |
// Selector of `log(uint256,uint256)`. |
||
| 457 |
mstore(0x00, 0xf666715a) |
||
| 458 |
mstore(0x20, p0) |
||
| 459 |
mstore(0x40, p1) |
||
| 460 |
} |
||
| 461 |
_sendLogPayload(0x1c, 0x44); |
||
| 462 |
/// @solidity memory-safe-assembly |
||
| 463 |
assembly {
|
||
| 464 |
mstore(0x00, m0) |
||
| 465 |
mstore(0x20, m1) |
||
| 466 |
mstore(0x40, m2) |
||
| 467 |
} |
||
| 468 |
} |
||
| 469 | |||
| 470 |
function log(uint256 p0, bytes32 p1) internal pure {
|
||
| 471 |
bytes32 m0; |
||
| 472 |
bytes32 m1; |
||
| 473 |
bytes32 m2; |
||
| 474 |
bytes32 m3; |
||
| 475 |
bytes32 m4; |
||
| 476 |
/// @solidity memory-safe-assembly |
||
| 477 |
assembly {
|
||
| 478 |
function writeString(pos, w) {
|
||
| 479 |
let length := 0 |
||
| 480 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 481 |
mstore(pos, length) |
||
| 482 |
let shift := sub(256, shl(3, length)) |
||
| 483 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 484 |
} |
||
| 485 |
m0 := mload(0x00) |
||
| 486 |
m1 := mload(0x20) |
||
| 487 |
m2 := mload(0x40) |
||
| 488 |
m3 := mload(0x60) |
||
| 489 |
m4 := mload(0x80) |
||
| 490 |
// Selector of `log(uint256,string)`. |
||
| 491 |
mstore(0x00, 0x643fd0df) |
||
| 492 |
mstore(0x20, p0) |
||
| 493 |
mstore(0x40, 0x40) |
||
| 494 |
writeString(0x60, p1) |
||
| 495 |
} |
||
| 496 |
_sendLogPayload(0x1c, 0x84); |
||
| 497 |
/// @solidity memory-safe-assembly |
||
| 498 |
assembly {
|
||
| 499 |
mstore(0x00, m0) |
||
| 500 |
mstore(0x20, m1) |
||
| 501 |
mstore(0x40, m2) |
||
| 502 |
mstore(0x60, m3) |
||
| 503 |
mstore(0x80, m4) |
||
| 504 |
} |
||
| 505 |
} |
||
| 506 | |||
| 507 |
function log(bytes32 p0, address p1) internal pure {
|
||
| 508 |
bytes32 m0; |
||
| 509 |
bytes32 m1; |
||
| 510 |
bytes32 m2; |
||
| 511 |
bytes32 m3; |
||
| 512 |
bytes32 m4; |
||
| 513 |
/// @solidity memory-safe-assembly |
||
| 514 |
assembly {
|
||
| 515 |
function writeString(pos, w) {
|
||
| 516 |
let length := 0 |
||
| 517 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 518 |
mstore(pos, length) |
||
| 519 |
let shift := sub(256, shl(3, length)) |
||
| 520 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 521 |
} |
||
| 522 |
m0 := mload(0x00) |
||
| 523 |
m1 := mload(0x20) |
||
| 524 |
m2 := mload(0x40) |
||
| 525 |
m3 := mload(0x60) |
||
| 526 |
m4 := mload(0x80) |
||
| 527 |
// Selector of `log(string,address)`. |
||
| 528 |
mstore(0x00, 0x319af333) |
||
| 529 |
mstore(0x20, 0x40) |
||
| 530 |
mstore(0x40, p1) |
||
| 531 |
writeString(0x60, p0) |
||
| 532 |
} |
||
| 533 |
_sendLogPayload(0x1c, 0x84); |
||
| 534 |
/// @solidity memory-safe-assembly |
||
| 535 |
assembly {
|
||
| 536 |
mstore(0x00, m0) |
||
| 537 |
mstore(0x20, m1) |
||
| 538 |
mstore(0x40, m2) |
||
| 539 |
mstore(0x60, m3) |
||
| 540 |
mstore(0x80, m4) |
||
| 541 |
} |
||
| 542 |
} |
||
| 543 | |||
| 544 |
function log(bytes32 p0, bool p1) internal pure {
|
||
| 545 |
bytes32 m0; |
||
| 546 |
bytes32 m1; |
||
| 547 |
bytes32 m2; |
||
| 548 |
bytes32 m3; |
||
| 549 |
bytes32 m4; |
||
| 550 |
/// @solidity memory-safe-assembly |
||
| 551 |
assembly {
|
||
| 552 |
function writeString(pos, w) {
|
||
| 553 |
let length := 0 |
||
| 554 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 555 |
mstore(pos, length) |
||
| 556 |
let shift := sub(256, shl(3, length)) |
||
| 557 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 558 |
} |
||
| 559 |
m0 := mload(0x00) |
||
| 560 |
m1 := mload(0x20) |
||
| 561 |
m2 := mload(0x40) |
||
| 562 |
m3 := mload(0x60) |
||
| 563 |
m4 := mload(0x80) |
||
| 564 |
// Selector of `log(string,bool)`. |
||
| 565 |
mstore(0x00, 0xc3b55635) |
||
| 566 |
mstore(0x20, 0x40) |
||
| 567 |
mstore(0x40, p1) |
||
| 568 |
writeString(0x60, p0) |
||
| 569 |
} |
||
| 570 |
_sendLogPayload(0x1c, 0x84); |
||
| 571 |
/// @solidity memory-safe-assembly |
||
| 572 |
assembly {
|
||
| 573 |
mstore(0x00, m0) |
||
| 574 |
mstore(0x20, m1) |
||
| 575 |
mstore(0x40, m2) |
||
| 576 |
mstore(0x60, m3) |
||
| 577 |
mstore(0x80, m4) |
||
| 578 |
} |
||
| 579 |
} |
||
| 580 | |||
| 581 |
function log(bytes32 p0, uint256 p1) internal pure {
|
||
| 582 |
bytes32 m0; |
||
| 583 |
bytes32 m1; |
||
| 584 |
bytes32 m2; |
||
| 585 |
bytes32 m3; |
||
| 586 |
bytes32 m4; |
||
| 587 |
/// @solidity memory-safe-assembly |
||
| 588 |
assembly {
|
||
| 589 |
function writeString(pos, w) {
|
||
| 590 |
let length := 0 |
||
| 591 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 592 |
mstore(pos, length) |
||
| 593 |
let shift := sub(256, shl(3, length)) |
||
| 594 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 595 |
} |
||
| 596 |
m0 := mload(0x00) |
||
| 597 |
m1 := mload(0x20) |
||
| 598 |
m2 := mload(0x40) |
||
| 599 |
m3 := mload(0x60) |
||
| 600 |
m4 := mload(0x80) |
||
| 601 |
// Selector of `log(string,uint256)`. |
||
| 602 |
mstore(0x00, 0xb60e72cc) |
||
| 603 |
mstore(0x20, 0x40) |
||
| 604 |
mstore(0x40, p1) |
||
| 605 |
writeString(0x60, p0) |
||
| 606 |
} |
||
| 607 |
_sendLogPayload(0x1c, 0x84); |
||
| 608 |
/// @solidity memory-safe-assembly |
||
| 609 |
assembly {
|
||
| 610 |
mstore(0x00, m0) |
||
| 611 |
mstore(0x20, m1) |
||
| 612 |
mstore(0x40, m2) |
||
| 613 |
mstore(0x60, m3) |
||
| 614 |
mstore(0x80, m4) |
||
| 615 |
} |
||
| 616 |
} |
||
| 617 | |||
| 618 |
function log(bytes32 p0, bytes32 p1) internal pure {
|
||
| 619 |
bytes32 m0; |
||
| 620 |
bytes32 m1; |
||
| 621 |
bytes32 m2; |
||
| 622 |
bytes32 m3; |
||
| 623 |
bytes32 m4; |
||
| 624 |
bytes32 m5; |
||
| 625 |
bytes32 m6; |
||
| 626 |
/// @solidity memory-safe-assembly |
||
| 627 |
assembly {
|
||
| 628 |
function writeString(pos, w) {
|
||
| 629 |
let length := 0 |
||
| 630 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 631 |
mstore(pos, length) |
||
| 632 |
let shift := sub(256, shl(3, length)) |
||
| 633 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 634 |
} |
||
| 635 |
m0 := mload(0x00) |
||
| 636 |
m1 := mload(0x20) |
||
| 637 |
m2 := mload(0x40) |
||
| 638 |
m3 := mload(0x60) |
||
| 639 |
m4 := mload(0x80) |
||
| 640 |
m5 := mload(0xa0) |
||
| 641 |
m6 := mload(0xc0) |
||
| 642 |
// Selector of `log(string,string)`. |
||
| 643 |
mstore(0x00, 0x4b5c4277) |
||
| 644 |
mstore(0x20, 0x40) |
||
| 645 |
mstore(0x40, 0x80) |
||
| 646 |
writeString(0x60, p0) |
||
| 647 |
writeString(0xa0, p1) |
||
| 648 |
} |
||
| 649 |
_sendLogPayload(0x1c, 0xc4); |
||
| 650 |
/// @solidity memory-safe-assembly |
||
| 651 |
assembly {
|
||
| 652 |
mstore(0x00, m0) |
||
| 653 |
mstore(0x20, m1) |
||
| 654 |
mstore(0x40, m2) |
||
| 655 |
mstore(0x60, m3) |
||
| 656 |
mstore(0x80, m4) |
||
| 657 |
mstore(0xa0, m5) |
||
| 658 |
mstore(0xc0, m6) |
||
| 659 |
} |
||
| 660 |
} |
||
| 661 | |||
| 662 |
function log(address p0, address p1, address p2) internal pure {
|
||
| 663 |
bytes32 m0; |
||
| 664 |
bytes32 m1; |
||
| 665 |
bytes32 m2; |
||
| 666 |
bytes32 m3; |
||
| 667 |
/// @solidity memory-safe-assembly |
||
| 668 |
assembly {
|
||
| 669 |
m0 := mload(0x00) |
||
| 670 |
m1 := mload(0x20) |
||
| 671 |
m2 := mload(0x40) |
||
| 672 |
m3 := mload(0x60) |
||
| 673 |
// Selector of `log(address,address,address)`. |
||
| 674 |
mstore(0x00, 0x018c84c2) |
||
| 675 |
mstore(0x20, p0) |
||
| 676 |
mstore(0x40, p1) |
||
| 677 |
mstore(0x60, p2) |
||
| 678 |
} |
||
| 679 |
_sendLogPayload(0x1c, 0x64); |
||
| 680 |
/// @solidity memory-safe-assembly |
||
| 681 |
assembly {
|
||
| 682 |
mstore(0x00, m0) |
||
| 683 |
mstore(0x20, m1) |
||
| 684 |
mstore(0x40, m2) |
||
| 685 |
mstore(0x60, m3) |
||
| 686 |
} |
||
| 687 |
} |
||
| 688 | |||
| 689 |
function log(address p0, address p1, bool p2) internal pure {
|
||
| 690 |
bytes32 m0; |
||
| 691 |
bytes32 m1; |
||
| 692 |
bytes32 m2; |
||
| 693 |
bytes32 m3; |
||
| 694 |
/// @solidity memory-safe-assembly |
||
| 695 |
assembly {
|
||
| 696 |
m0 := mload(0x00) |
||
| 697 |
m1 := mload(0x20) |
||
| 698 |
m2 := mload(0x40) |
||
| 699 |
m3 := mload(0x60) |
||
| 700 |
// Selector of `log(address,address,bool)`. |
||
| 701 |
mstore(0x00, 0xf2a66286) |
||
| 702 |
mstore(0x20, p0) |
||
| 703 |
mstore(0x40, p1) |
||
| 704 |
mstore(0x60, p2) |
||
| 705 |
} |
||
| 706 |
_sendLogPayload(0x1c, 0x64); |
||
| 707 |
/// @solidity memory-safe-assembly |
||
| 708 |
assembly {
|
||
| 709 |
mstore(0x00, m0) |
||
| 710 |
mstore(0x20, m1) |
||
| 711 |
mstore(0x40, m2) |
||
| 712 |
mstore(0x60, m3) |
||
| 713 |
} |
||
| 714 |
} |
||
| 715 | |||
| 716 |
function log(address p0, address p1, uint256 p2) internal pure {
|
||
| 717 |
bytes32 m0; |
||
| 718 |
bytes32 m1; |
||
| 719 |
bytes32 m2; |
||
| 720 |
bytes32 m3; |
||
| 721 |
/// @solidity memory-safe-assembly |
||
| 722 |
assembly {
|
||
| 723 |
m0 := mload(0x00) |
||
| 724 |
m1 := mload(0x20) |
||
| 725 |
m2 := mload(0x40) |
||
| 726 |
m3 := mload(0x60) |
||
| 727 |
// Selector of `log(address,address,uint256)`. |
||
| 728 |
mstore(0x00, 0x17fe6185) |
||
| 729 |
mstore(0x20, p0) |
||
| 730 |
mstore(0x40, p1) |
||
| 731 |
mstore(0x60, p2) |
||
| 732 |
} |
||
| 733 |
_sendLogPayload(0x1c, 0x64); |
||
| 734 |
/// @solidity memory-safe-assembly |
||
| 735 |
assembly {
|
||
| 736 |
mstore(0x00, m0) |
||
| 737 |
mstore(0x20, m1) |
||
| 738 |
mstore(0x40, m2) |
||
| 739 |
mstore(0x60, m3) |
||
| 740 |
} |
||
| 741 |
} |
||
| 742 | |||
| 743 |
function log(address p0, address p1, bytes32 p2) internal pure {
|
||
| 744 |
bytes32 m0; |
||
| 745 |
bytes32 m1; |
||
| 746 |
bytes32 m2; |
||
| 747 |
bytes32 m3; |
||
| 748 |
bytes32 m4; |
||
| 749 |
bytes32 m5; |
||
| 750 |
/// @solidity memory-safe-assembly |
||
| 751 |
assembly {
|
||
| 752 |
function writeString(pos, w) {
|
||
| 753 |
let length := 0 |
||
| 754 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 755 |
mstore(pos, length) |
||
| 756 |
let shift := sub(256, shl(3, length)) |
||
| 757 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 758 |
} |
||
| 759 |
m0 := mload(0x00) |
||
| 760 |
m1 := mload(0x20) |
||
| 761 |
m2 := mload(0x40) |
||
| 762 |
m3 := mload(0x60) |
||
| 763 |
m4 := mload(0x80) |
||
| 764 |
m5 := mload(0xa0) |
||
| 765 |
// Selector of `log(address,address,string)`. |
||
| 766 |
mstore(0x00, 0x007150be) |
||
| 767 |
mstore(0x20, p0) |
||
| 768 |
mstore(0x40, p1) |
||
| 769 |
mstore(0x60, 0x60) |
||
| 770 |
writeString(0x80, p2) |
||
| 771 |
} |
||
| 772 |
_sendLogPayload(0x1c, 0xa4); |
||
| 773 |
/// @solidity memory-safe-assembly |
||
| 774 |
assembly {
|
||
| 775 |
mstore(0x00, m0) |
||
| 776 |
mstore(0x20, m1) |
||
| 777 |
mstore(0x40, m2) |
||
| 778 |
mstore(0x60, m3) |
||
| 779 |
mstore(0x80, m4) |
||
| 780 |
mstore(0xa0, m5) |
||
| 781 |
} |
||
| 782 |
} |
||
| 783 | |||
| 784 |
function log(address p0, bool p1, address p2) internal pure {
|
||
| 785 |
bytes32 m0; |
||
| 786 |
bytes32 m1; |
||
| 787 |
bytes32 m2; |
||
| 788 |
bytes32 m3; |
||
| 789 |
/// @solidity memory-safe-assembly |
||
| 790 |
assembly {
|
||
| 791 |
m0 := mload(0x00) |
||
| 792 |
m1 := mload(0x20) |
||
| 793 |
m2 := mload(0x40) |
||
| 794 |
m3 := mload(0x60) |
||
| 795 |
// Selector of `log(address,bool,address)`. |
||
| 796 |
mstore(0x00, 0xf11699ed) |
||
| 797 |
mstore(0x20, p0) |
||
| 798 |
mstore(0x40, p1) |
||
| 799 |
mstore(0x60, p2) |
||
| 800 |
} |
||
| 801 |
_sendLogPayload(0x1c, 0x64); |
||
| 802 |
/// @solidity memory-safe-assembly |
||
| 803 |
assembly {
|
||
| 804 |
mstore(0x00, m0) |
||
| 805 |
mstore(0x20, m1) |
||
| 806 |
mstore(0x40, m2) |
||
| 807 |
mstore(0x60, m3) |
||
| 808 |
} |
||
| 809 |
} |
||
| 810 | |||
| 811 |
function log(address p0, bool p1, bool p2) internal pure {
|
||
| 812 |
bytes32 m0; |
||
| 813 |
bytes32 m1; |
||
| 814 |
bytes32 m2; |
||
| 815 |
bytes32 m3; |
||
| 816 |
/// @solidity memory-safe-assembly |
||
| 817 |
assembly {
|
||
| 818 |
m0 := mload(0x00) |
||
| 819 |
m1 := mload(0x20) |
||
| 820 |
m2 := mload(0x40) |
||
| 821 |
m3 := mload(0x60) |
||
| 822 |
// Selector of `log(address,bool,bool)`. |
||
| 823 |
mstore(0x00, 0xeb830c92) |
||
| 824 |
mstore(0x20, p0) |
||
| 825 |
mstore(0x40, p1) |
||
| 826 |
mstore(0x60, p2) |
||
| 827 |
} |
||
| 828 |
_sendLogPayload(0x1c, 0x64); |
||
| 829 |
/// @solidity memory-safe-assembly |
||
| 830 |
assembly {
|
||
| 831 |
mstore(0x00, m0) |
||
| 832 |
mstore(0x20, m1) |
||
| 833 |
mstore(0x40, m2) |
||
| 834 |
mstore(0x60, m3) |
||
| 835 |
} |
||
| 836 |
} |
||
| 837 | |||
| 838 |
function log(address p0, bool p1, uint256 p2) internal pure {
|
||
| 839 |
bytes32 m0; |
||
| 840 |
bytes32 m1; |
||
| 841 |
bytes32 m2; |
||
| 842 |
bytes32 m3; |
||
| 843 |
/// @solidity memory-safe-assembly |
||
| 844 |
assembly {
|
||
| 845 |
m0 := mload(0x00) |
||
| 846 |
m1 := mload(0x20) |
||
| 847 |
m2 := mload(0x40) |
||
| 848 |
m3 := mload(0x60) |
||
| 849 |
// Selector of `log(address,bool,uint256)`. |
||
| 850 |
mstore(0x00, 0x9c4f99fb) |
||
| 851 |
mstore(0x20, p0) |
||
| 852 |
mstore(0x40, p1) |
||
| 853 |
mstore(0x60, p2) |
||
| 854 |
} |
||
| 855 |
_sendLogPayload(0x1c, 0x64); |
||
| 856 |
/// @solidity memory-safe-assembly |
||
| 857 |
assembly {
|
||
| 858 |
mstore(0x00, m0) |
||
| 859 |
mstore(0x20, m1) |
||
| 860 |
mstore(0x40, m2) |
||
| 861 |
mstore(0x60, m3) |
||
| 862 |
} |
||
| 863 |
} |
||
| 864 | |||
| 865 |
function log(address p0, bool p1, bytes32 p2) internal pure {
|
||
| 866 |
bytes32 m0; |
||
| 867 |
bytes32 m1; |
||
| 868 |
bytes32 m2; |
||
| 869 |
bytes32 m3; |
||
| 870 |
bytes32 m4; |
||
| 871 |
bytes32 m5; |
||
| 872 |
/// @solidity memory-safe-assembly |
||
| 873 |
assembly {
|
||
| 874 |
function writeString(pos, w) {
|
||
| 875 |
let length := 0 |
||
| 876 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 877 |
mstore(pos, length) |
||
| 878 |
let shift := sub(256, shl(3, length)) |
||
| 879 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 880 |
} |
||
| 881 |
m0 := mload(0x00) |
||
| 882 |
m1 := mload(0x20) |
||
| 883 |
m2 := mload(0x40) |
||
| 884 |
m3 := mload(0x60) |
||
| 885 |
m4 := mload(0x80) |
||
| 886 |
m5 := mload(0xa0) |
||
| 887 |
// Selector of `log(address,bool,string)`. |
||
| 888 |
mstore(0x00, 0x212255cc) |
||
| 889 |
mstore(0x20, p0) |
||
| 890 |
mstore(0x40, p1) |
||
| 891 |
mstore(0x60, 0x60) |
||
| 892 |
writeString(0x80, p2) |
||
| 893 |
} |
||
| 894 |
_sendLogPayload(0x1c, 0xa4); |
||
| 895 |
/// @solidity memory-safe-assembly |
||
| 896 |
assembly {
|
||
| 897 |
mstore(0x00, m0) |
||
| 898 |
mstore(0x20, m1) |
||
| 899 |
mstore(0x40, m2) |
||
| 900 |
mstore(0x60, m3) |
||
| 901 |
mstore(0x80, m4) |
||
| 902 |
mstore(0xa0, m5) |
||
| 903 |
} |
||
| 904 |
} |
||
| 905 | |||
| 906 |
function log(address p0, uint256 p1, address p2) internal pure {
|
||
| 907 |
bytes32 m0; |
||
| 908 |
bytes32 m1; |
||
| 909 |
bytes32 m2; |
||
| 910 |
bytes32 m3; |
||
| 911 |
/// @solidity memory-safe-assembly |
||
| 912 |
assembly {
|
||
| 913 |
m0 := mload(0x00) |
||
| 914 |
m1 := mload(0x20) |
||
| 915 |
m2 := mload(0x40) |
||
| 916 |
m3 := mload(0x60) |
||
| 917 |
// Selector of `log(address,uint256,address)`. |
||
| 918 |
mstore(0x00, 0x7bc0d848) |
||
| 919 |
mstore(0x20, p0) |
||
| 920 |
mstore(0x40, p1) |
||
| 921 |
mstore(0x60, p2) |
||
| 922 |
} |
||
| 923 |
_sendLogPayload(0x1c, 0x64); |
||
| 924 |
/// @solidity memory-safe-assembly |
||
| 925 |
assembly {
|
||
| 926 |
mstore(0x00, m0) |
||
| 927 |
mstore(0x20, m1) |
||
| 928 |
mstore(0x40, m2) |
||
| 929 |
mstore(0x60, m3) |
||
| 930 |
} |
||
| 931 |
} |
||
| 932 | |||
| 933 |
function log(address p0, uint256 p1, bool p2) internal pure {
|
||
| 934 |
bytes32 m0; |
||
| 935 |
bytes32 m1; |
||
| 936 |
bytes32 m2; |
||
| 937 |
bytes32 m3; |
||
| 938 |
/// @solidity memory-safe-assembly |
||
| 939 |
assembly {
|
||
| 940 |
m0 := mload(0x00) |
||
| 941 |
m1 := mload(0x20) |
||
| 942 |
m2 := mload(0x40) |
||
| 943 |
m3 := mload(0x60) |
||
| 944 |
// Selector of `log(address,uint256,bool)`. |
||
| 945 |
mstore(0x00, 0x678209a8) |
||
| 946 |
mstore(0x20, p0) |
||
| 947 |
mstore(0x40, p1) |
||
| 948 |
mstore(0x60, p2) |
||
| 949 |
} |
||
| 950 |
_sendLogPayload(0x1c, 0x64); |
||
| 951 |
/// @solidity memory-safe-assembly |
||
| 952 |
assembly {
|
||
| 953 |
mstore(0x00, m0) |
||
| 954 |
mstore(0x20, m1) |
||
| 955 |
mstore(0x40, m2) |
||
| 956 |
mstore(0x60, m3) |
||
| 957 |
} |
||
| 958 |
} |
||
| 959 | |||
| 960 |
function log(address p0, uint256 p1, uint256 p2) internal pure {
|
||
| 961 |
bytes32 m0; |
||
| 962 |
bytes32 m1; |
||
| 963 |
bytes32 m2; |
||
| 964 |
bytes32 m3; |
||
| 965 |
/// @solidity memory-safe-assembly |
||
| 966 |
assembly {
|
||
| 967 |
m0 := mload(0x00) |
||
| 968 |
m1 := mload(0x20) |
||
| 969 |
m2 := mload(0x40) |
||
| 970 |
m3 := mload(0x60) |
||
| 971 |
// Selector of `log(address,uint256,uint256)`. |
||
| 972 |
mstore(0x00, 0xb69bcaf6) |
||
| 973 |
mstore(0x20, p0) |
||
| 974 |
mstore(0x40, p1) |
||
| 975 |
mstore(0x60, p2) |
||
| 976 |
} |
||
| 977 |
_sendLogPayload(0x1c, 0x64); |
||
| 978 |
/// @solidity memory-safe-assembly |
||
| 979 |
assembly {
|
||
| 980 |
mstore(0x00, m0) |
||
| 981 |
mstore(0x20, m1) |
||
| 982 |
mstore(0x40, m2) |
||
| 983 |
mstore(0x60, m3) |
||
| 984 |
} |
||
| 985 |
} |
||
| 986 | |||
| 987 |
function log(address p0, uint256 p1, bytes32 p2) internal pure {
|
||
| 988 |
bytes32 m0; |
||
| 989 |
bytes32 m1; |
||
| 990 |
bytes32 m2; |
||
| 991 |
bytes32 m3; |
||
| 992 |
bytes32 m4; |
||
| 993 |
bytes32 m5; |
||
| 994 |
/// @solidity memory-safe-assembly |
||
| 995 |
assembly {
|
||
| 996 |
function writeString(pos, w) {
|
||
| 997 |
let length := 0 |
||
| 998 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 999 |
mstore(pos, length) |
||
| 1000 |
let shift := sub(256, shl(3, length)) |
||
| 1001 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1002 |
} |
||
| 1003 |
m0 := mload(0x00) |
||
| 1004 |
m1 := mload(0x20) |
||
| 1005 |
m2 := mload(0x40) |
||
| 1006 |
m3 := mload(0x60) |
||
| 1007 |
m4 := mload(0x80) |
||
| 1008 |
m5 := mload(0xa0) |
||
| 1009 |
// Selector of `log(address,uint256,string)`. |
||
| 1010 |
mstore(0x00, 0xa1f2e8aa) |
||
| 1011 |
mstore(0x20, p0) |
||
| 1012 |
mstore(0x40, p1) |
||
| 1013 |
mstore(0x60, 0x60) |
||
| 1014 |
writeString(0x80, p2) |
||
| 1015 |
} |
||
| 1016 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1017 |
/// @solidity memory-safe-assembly |
||
| 1018 |
assembly {
|
||
| 1019 |
mstore(0x00, m0) |
||
| 1020 |
mstore(0x20, m1) |
||
| 1021 |
mstore(0x40, m2) |
||
| 1022 |
mstore(0x60, m3) |
||
| 1023 |
mstore(0x80, m4) |
||
| 1024 |
mstore(0xa0, m5) |
||
| 1025 |
} |
||
| 1026 |
} |
||
| 1027 | |||
| 1028 |
function log(address p0, bytes32 p1, address p2) internal pure {
|
||
| 1029 |
bytes32 m0; |
||
| 1030 |
bytes32 m1; |
||
| 1031 |
bytes32 m2; |
||
| 1032 |
bytes32 m3; |
||
| 1033 |
bytes32 m4; |
||
| 1034 |
bytes32 m5; |
||
| 1035 |
/// @solidity memory-safe-assembly |
||
| 1036 |
assembly {
|
||
| 1037 |
function writeString(pos, w) {
|
||
| 1038 |
let length := 0 |
||
| 1039 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1040 |
mstore(pos, length) |
||
| 1041 |
let shift := sub(256, shl(3, length)) |
||
| 1042 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1043 |
} |
||
| 1044 |
m0 := mload(0x00) |
||
| 1045 |
m1 := mload(0x20) |
||
| 1046 |
m2 := mload(0x40) |
||
| 1047 |
m3 := mload(0x60) |
||
| 1048 |
m4 := mload(0x80) |
||
| 1049 |
m5 := mload(0xa0) |
||
| 1050 |
// Selector of `log(address,string,address)`. |
||
| 1051 |
mstore(0x00, 0xf08744e8) |
||
| 1052 |
mstore(0x20, p0) |
||
| 1053 |
mstore(0x40, 0x60) |
||
| 1054 |
mstore(0x60, p2) |
||
| 1055 |
writeString(0x80, p1) |
||
| 1056 |
} |
||
| 1057 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1058 |
/// @solidity memory-safe-assembly |
||
| 1059 |
assembly {
|
||
| 1060 |
mstore(0x00, m0) |
||
| 1061 |
mstore(0x20, m1) |
||
| 1062 |
mstore(0x40, m2) |
||
| 1063 |
mstore(0x60, m3) |
||
| 1064 |
mstore(0x80, m4) |
||
| 1065 |
mstore(0xa0, m5) |
||
| 1066 |
} |
||
| 1067 |
} |
||
| 1068 | |||
| 1069 |
function log(address p0, bytes32 p1, bool p2) internal pure {
|
||
| 1070 |
bytes32 m0; |
||
| 1071 |
bytes32 m1; |
||
| 1072 |
bytes32 m2; |
||
| 1073 |
bytes32 m3; |
||
| 1074 |
bytes32 m4; |
||
| 1075 |
bytes32 m5; |
||
| 1076 |
/// @solidity memory-safe-assembly |
||
| 1077 |
assembly {
|
||
| 1078 |
function writeString(pos, w) {
|
||
| 1079 |
let length := 0 |
||
| 1080 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1081 |
mstore(pos, length) |
||
| 1082 |
let shift := sub(256, shl(3, length)) |
||
| 1083 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1084 |
} |
||
| 1085 |
m0 := mload(0x00) |
||
| 1086 |
m1 := mload(0x20) |
||
| 1087 |
m2 := mload(0x40) |
||
| 1088 |
m3 := mload(0x60) |
||
| 1089 |
m4 := mload(0x80) |
||
| 1090 |
m5 := mload(0xa0) |
||
| 1091 |
// Selector of `log(address,string,bool)`. |
||
| 1092 |
mstore(0x00, 0xcf020fb1) |
||
| 1093 |
mstore(0x20, p0) |
||
| 1094 |
mstore(0x40, 0x60) |
||
| 1095 |
mstore(0x60, p2) |
||
| 1096 |
writeString(0x80, p1) |
||
| 1097 |
} |
||
| 1098 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1099 |
/// @solidity memory-safe-assembly |
||
| 1100 |
assembly {
|
||
| 1101 |
mstore(0x00, m0) |
||
| 1102 |
mstore(0x20, m1) |
||
| 1103 |
mstore(0x40, m2) |
||
| 1104 |
mstore(0x60, m3) |
||
| 1105 |
mstore(0x80, m4) |
||
| 1106 |
mstore(0xa0, m5) |
||
| 1107 |
} |
||
| 1108 |
} |
||
| 1109 | |||
| 1110 |
function log(address p0, bytes32 p1, uint256 p2) internal pure {
|
||
| 1111 |
bytes32 m0; |
||
| 1112 |
bytes32 m1; |
||
| 1113 |
bytes32 m2; |
||
| 1114 |
bytes32 m3; |
||
| 1115 |
bytes32 m4; |
||
| 1116 |
bytes32 m5; |
||
| 1117 |
/// @solidity memory-safe-assembly |
||
| 1118 |
assembly {
|
||
| 1119 |
function writeString(pos, w) {
|
||
| 1120 |
let length := 0 |
||
| 1121 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1122 |
mstore(pos, length) |
||
| 1123 |
let shift := sub(256, shl(3, length)) |
||
| 1124 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1125 |
} |
||
| 1126 |
m0 := mload(0x00) |
||
| 1127 |
m1 := mload(0x20) |
||
| 1128 |
m2 := mload(0x40) |
||
| 1129 |
m3 := mload(0x60) |
||
| 1130 |
m4 := mload(0x80) |
||
| 1131 |
m5 := mload(0xa0) |
||
| 1132 |
// Selector of `log(address,string,uint256)`. |
||
| 1133 |
mstore(0x00, 0x67dd6ff1) |
||
| 1134 |
mstore(0x20, p0) |
||
| 1135 |
mstore(0x40, 0x60) |
||
| 1136 |
mstore(0x60, p2) |
||
| 1137 |
writeString(0x80, p1) |
||
| 1138 |
} |
||
| 1139 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1140 |
/// @solidity memory-safe-assembly |
||
| 1141 |
assembly {
|
||
| 1142 |
mstore(0x00, m0) |
||
| 1143 |
mstore(0x20, m1) |
||
| 1144 |
mstore(0x40, m2) |
||
| 1145 |
mstore(0x60, m3) |
||
| 1146 |
mstore(0x80, m4) |
||
| 1147 |
mstore(0xa0, m5) |
||
| 1148 |
} |
||
| 1149 |
} |
||
| 1150 | |||
| 1151 |
function log(address p0, bytes32 p1, bytes32 p2) internal pure {
|
||
| 1152 |
bytes32 m0; |
||
| 1153 |
bytes32 m1; |
||
| 1154 |
bytes32 m2; |
||
| 1155 |
bytes32 m3; |
||
| 1156 |
bytes32 m4; |
||
| 1157 |
bytes32 m5; |
||
| 1158 |
bytes32 m6; |
||
| 1159 |
bytes32 m7; |
||
| 1160 |
/// @solidity memory-safe-assembly |
||
| 1161 |
assembly {
|
||
| 1162 |
function writeString(pos, w) {
|
||
| 1163 |
let length := 0 |
||
| 1164 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1165 |
mstore(pos, length) |
||
| 1166 |
let shift := sub(256, shl(3, length)) |
||
| 1167 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1168 |
} |
||
| 1169 |
m0 := mload(0x00) |
||
| 1170 |
m1 := mload(0x20) |
||
| 1171 |
m2 := mload(0x40) |
||
| 1172 |
m3 := mload(0x60) |
||
| 1173 |
m4 := mload(0x80) |
||
| 1174 |
m5 := mload(0xa0) |
||
| 1175 |
m6 := mload(0xc0) |
||
| 1176 |
m7 := mload(0xe0) |
||
| 1177 |
// Selector of `log(address,string,string)`. |
||
| 1178 |
mstore(0x00, 0xfb772265) |
||
| 1179 |
mstore(0x20, p0) |
||
| 1180 |
mstore(0x40, 0x60) |
||
| 1181 |
mstore(0x60, 0xa0) |
||
| 1182 |
writeString(0x80, p1) |
||
| 1183 |
writeString(0xc0, p2) |
||
| 1184 |
} |
||
| 1185 |
_sendLogPayload(0x1c, 0xe4); |
||
| 1186 |
/// @solidity memory-safe-assembly |
||
| 1187 |
assembly {
|
||
| 1188 |
mstore(0x00, m0) |
||
| 1189 |
mstore(0x20, m1) |
||
| 1190 |
mstore(0x40, m2) |
||
| 1191 |
mstore(0x60, m3) |
||
| 1192 |
mstore(0x80, m4) |
||
| 1193 |
mstore(0xa0, m5) |
||
| 1194 |
mstore(0xc0, m6) |
||
| 1195 |
mstore(0xe0, m7) |
||
| 1196 |
} |
||
| 1197 |
} |
||
| 1198 | |||
| 1199 |
function log(bool p0, address p1, address p2) internal pure {
|
||
| 1200 |
bytes32 m0; |
||
| 1201 |
bytes32 m1; |
||
| 1202 |
bytes32 m2; |
||
| 1203 |
bytes32 m3; |
||
| 1204 |
/// @solidity memory-safe-assembly |
||
| 1205 |
assembly {
|
||
| 1206 |
m0 := mload(0x00) |
||
| 1207 |
m1 := mload(0x20) |
||
| 1208 |
m2 := mload(0x40) |
||
| 1209 |
m3 := mload(0x60) |
||
| 1210 |
// Selector of `log(bool,address,address)`. |
||
| 1211 |
mstore(0x00, 0xd2763667) |
||
| 1212 |
mstore(0x20, p0) |
||
| 1213 |
mstore(0x40, p1) |
||
| 1214 |
mstore(0x60, p2) |
||
| 1215 |
} |
||
| 1216 |
_sendLogPayload(0x1c, 0x64); |
||
| 1217 |
/// @solidity memory-safe-assembly |
||
| 1218 |
assembly {
|
||
| 1219 |
mstore(0x00, m0) |
||
| 1220 |
mstore(0x20, m1) |
||
| 1221 |
mstore(0x40, m2) |
||
| 1222 |
mstore(0x60, m3) |
||
| 1223 |
} |
||
| 1224 |
} |
||
| 1225 | |||
| 1226 |
function log(bool p0, address p1, bool p2) internal pure {
|
||
| 1227 |
bytes32 m0; |
||
| 1228 |
bytes32 m1; |
||
| 1229 |
bytes32 m2; |
||
| 1230 |
bytes32 m3; |
||
| 1231 |
/// @solidity memory-safe-assembly |
||
| 1232 |
assembly {
|
||
| 1233 |
m0 := mload(0x00) |
||
| 1234 |
m1 := mload(0x20) |
||
| 1235 |
m2 := mload(0x40) |
||
| 1236 |
m3 := mload(0x60) |
||
| 1237 |
// Selector of `log(bool,address,bool)`. |
||
| 1238 |
mstore(0x00, 0x18c9c746) |
||
| 1239 |
mstore(0x20, p0) |
||
| 1240 |
mstore(0x40, p1) |
||
| 1241 |
mstore(0x60, p2) |
||
| 1242 |
} |
||
| 1243 |
_sendLogPayload(0x1c, 0x64); |
||
| 1244 |
/// @solidity memory-safe-assembly |
||
| 1245 |
assembly {
|
||
| 1246 |
mstore(0x00, m0) |
||
| 1247 |
mstore(0x20, m1) |
||
| 1248 |
mstore(0x40, m2) |
||
| 1249 |
mstore(0x60, m3) |
||
| 1250 |
} |
||
| 1251 |
} |
||
| 1252 | |||
| 1253 |
function log(bool p0, address p1, uint256 p2) internal pure {
|
||
| 1254 |
bytes32 m0; |
||
| 1255 |
bytes32 m1; |
||
| 1256 |
bytes32 m2; |
||
| 1257 |
bytes32 m3; |
||
| 1258 |
/// @solidity memory-safe-assembly |
||
| 1259 |
assembly {
|
||
| 1260 |
m0 := mload(0x00) |
||
| 1261 |
m1 := mload(0x20) |
||
| 1262 |
m2 := mload(0x40) |
||
| 1263 |
m3 := mload(0x60) |
||
| 1264 |
// Selector of `log(bool,address,uint256)`. |
||
| 1265 |
mstore(0x00, 0x5f7b9afb) |
||
| 1266 |
mstore(0x20, p0) |
||
| 1267 |
mstore(0x40, p1) |
||
| 1268 |
mstore(0x60, p2) |
||
| 1269 |
} |
||
| 1270 |
_sendLogPayload(0x1c, 0x64); |
||
| 1271 |
/// @solidity memory-safe-assembly |
||
| 1272 |
assembly {
|
||
| 1273 |
mstore(0x00, m0) |
||
| 1274 |
mstore(0x20, m1) |
||
| 1275 |
mstore(0x40, m2) |
||
| 1276 |
mstore(0x60, m3) |
||
| 1277 |
} |
||
| 1278 |
} |
||
| 1279 | |||
| 1280 |
function log(bool p0, address p1, bytes32 p2) internal pure {
|
||
| 1281 |
bytes32 m0; |
||
| 1282 |
bytes32 m1; |
||
| 1283 |
bytes32 m2; |
||
| 1284 |
bytes32 m3; |
||
| 1285 |
bytes32 m4; |
||
| 1286 |
bytes32 m5; |
||
| 1287 |
/// @solidity memory-safe-assembly |
||
| 1288 |
assembly {
|
||
| 1289 |
function writeString(pos, w) {
|
||
| 1290 |
let length := 0 |
||
| 1291 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1292 |
mstore(pos, length) |
||
| 1293 |
let shift := sub(256, shl(3, length)) |
||
| 1294 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1295 |
} |
||
| 1296 |
m0 := mload(0x00) |
||
| 1297 |
m1 := mload(0x20) |
||
| 1298 |
m2 := mload(0x40) |
||
| 1299 |
m3 := mload(0x60) |
||
| 1300 |
m4 := mload(0x80) |
||
| 1301 |
m5 := mload(0xa0) |
||
| 1302 |
// Selector of `log(bool,address,string)`. |
||
| 1303 |
mstore(0x00, 0xde9a9270) |
||
| 1304 |
mstore(0x20, p0) |
||
| 1305 |
mstore(0x40, p1) |
||
| 1306 |
mstore(0x60, 0x60) |
||
| 1307 |
writeString(0x80, p2) |
||
| 1308 |
} |
||
| 1309 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1310 |
/// @solidity memory-safe-assembly |
||
| 1311 |
assembly {
|
||
| 1312 |
mstore(0x00, m0) |
||
| 1313 |
mstore(0x20, m1) |
||
| 1314 |
mstore(0x40, m2) |
||
| 1315 |
mstore(0x60, m3) |
||
| 1316 |
mstore(0x80, m4) |
||
| 1317 |
mstore(0xa0, m5) |
||
| 1318 |
} |
||
| 1319 |
} |
||
| 1320 | |||
| 1321 |
function log(bool p0, bool p1, address p2) internal pure {
|
||
| 1322 |
bytes32 m0; |
||
| 1323 |
bytes32 m1; |
||
| 1324 |
bytes32 m2; |
||
| 1325 |
bytes32 m3; |
||
| 1326 |
/// @solidity memory-safe-assembly |
||
| 1327 |
assembly {
|
||
| 1328 |
m0 := mload(0x00) |
||
| 1329 |
m1 := mload(0x20) |
||
| 1330 |
m2 := mload(0x40) |
||
| 1331 |
m3 := mload(0x60) |
||
| 1332 |
// Selector of `log(bool,bool,address)`. |
||
| 1333 |
mstore(0x00, 0x1078f68d) |
||
| 1334 |
mstore(0x20, p0) |
||
| 1335 |
mstore(0x40, p1) |
||
| 1336 |
mstore(0x60, p2) |
||
| 1337 |
} |
||
| 1338 |
_sendLogPayload(0x1c, 0x64); |
||
| 1339 |
/// @solidity memory-safe-assembly |
||
| 1340 |
assembly {
|
||
| 1341 |
mstore(0x00, m0) |
||
| 1342 |
mstore(0x20, m1) |
||
| 1343 |
mstore(0x40, m2) |
||
| 1344 |
mstore(0x60, m3) |
||
| 1345 |
} |
||
| 1346 |
} |
||
| 1347 | |||
| 1348 |
function log(bool p0, bool p1, bool p2) internal pure {
|
||
| 1349 |
bytes32 m0; |
||
| 1350 |
bytes32 m1; |
||
| 1351 |
bytes32 m2; |
||
| 1352 |
bytes32 m3; |
||
| 1353 |
/// @solidity memory-safe-assembly |
||
| 1354 |
assembly {
|
||
| 1355 |
m0 := mload(0x00) |
||
| 1356 |
m1 := mload(0x20) |
||
| 1357 |
m2 := mload(0x40) |
||
| 1358 |
m3 := mload(0x60) |
||
| 1359 |
// Selector of `log(bool,bool,bool)`. |
||
| 1360 |
mstore(0x00, 0x50709698) |
||
| 1361 |
mstore(0x20, p0) |
||
| 1362 |
mstore(0x40, p1) |
||
| 1363 |
mstore(0x60, p2) |
||
| 1364 |
} |
||
| 1365 |
_sendLogPayload(0x1c, 0x64); |
||
| 1366 |
/// @solidity memory-safe-assembly |
||
| 1367 |
assembly {
|
||
| 1368 |
mstore(0x00, m0) |
||
| 1369 |
mstore(0x20, m1) |
||
| 1370 |
mstore(0x40, m2) |
||
| 1371 |
mstore(0x60, m3) |
||
| 1372 |
} |
||
| 1373 |
} |
||
| 1374 | |||
| 1375 |
function log(bool p0, bool p1, uint256 p2) internal pure {
|
||
| 1376 |
bytes32 m0; |
||
| 1377 |
bytes32 m1; |
||
| 1378 |
bytes32 m2; |
||
| 1379 |
bytes32 m3; |
||
| 1380 |
/// @solidity memory-safe-assembly |
||
| 1381 |
assembly {
|
||
| 1382 |
m0 := mload(0x00) |
||
| 1383 |
m1 := mload(0x20) |
||
| 1384 |
m2 := mload(0x40) |
||
| 1385 |
m3 := mload(0x60) |
||
| 1386 |
// Selector of `log(bool,bool,uint256)`. |
||
| 1387 |
mstore(0x00, 0x12f21602) |
||
| 1388 |
mstore(0x20, p0) |
||
| 1389 |
mstore(0x40, p1) |
||
| 1390 |
mstore(0x60, p2) |
||
| 1391 |
} |
||
| 1392 |
_sendLogPayload(0x1c, 0x64); |
||
| 1393 |
/// @solidity memory-safe-assembly |
||
| 1394 |
assembly {
|
||
| 1395 |
mstore(0x00, m0) |
||
| 1396 |
mstore(0x20, m1) |
||
| 1397 |
mstore(0x40, m2) |
||
| 1398 |
mstore(0x60, m3) |
||
| 1399 |
} |
||
| 1400 |
} |
||
| 1401 | |||
| 1402 |
function log(bool p0, bool p1, bytes32 p2) internal pure {
|
||
| 1403 |
bytes32 m0; |
||
| 1404 |
bytes32 m1; |
||
| 1405 |
bytes32 m2; |
||
| 1406 |
bytes32 m3; |
||
| 1407 |
bytes32 m4; |
||
| 1408 |
bytes32 m5; |
||
| 1409 |
/// @solidity memory-safe-assembly |
||
| 1410 |
assembly {
|
||
| 1411 |
function writeString(pos, w) {
|
||
| 1412 |
let length := 0 |
||
| 1413 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1414 |
mstore(pos, length) |
||
| 1415 |
let shift := sub(256, shl(3, length)) |
||
| 1416 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1417 |
} |
||
| 1418 |
m0 := mload(0x00) |
||
| 1419 |
m1 := mload(0x20) |
||
| 1420 |
m2 := mload(0x40) |
||
| 1421 |
m3 := mload(0x60) |
||
| 1422 |
m4 := mload(0x80) |
||
| 1423 |
m5 := mload(0xa0) |
||
| 1424 |
// Selector of `log(bool,bool,string)`. |
||
| 1425 |
mstore(0x00, 0x2555fa46) |
||
| 1426 |
mstore(0x20, p0) |
||
| 1427 |
mstore(0x40, p1) |
||
| 1428 |
mstore(0x60, 0x60) |
||
| 1429 |
writeString(0x80, p2) |
||
| 1430 |
} |
||
| 1431 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1432 |
/// @solidity memory-safe-assembly |
||
| 1433 |
assembly {
|
||
| 1434 |
mstore(0x00, m0) |
||
| 1435 |
mstore(0x20, m1) |
||
| 1436 |
mstore(0x40, m2) |
||
| 1437 |
mstore(0x60, m3) |
||
| 1438 |
mstore(0x80, m4) |
||
| 1439 |
mstore(0xa0, m5) |
||
| 1440 |
} |
||
| 1441 |
} |
||
| 1442 | |||
| 1443 |
function log(bool p0, uint256 p1, address p2) internal pure {
|
||
| 1444 |
bytes32 m0; |
||
| 1445 |
bytes32 m1; |
||
| 1446 |
bytes32 m2; |
||
| 1447 |
bytes32 m3; |
||
| 1448 |
/// @solidity memory-safe-assembly |
||
| 1449 |
assembly {
|
||
| 1450 |
m0 := mload(0x00) |
||
| 1451 |
m1 := mload(0x20) |
||
| 1452 |
m2 := mload(0x40) |
||
| 1453 |
m3 := mload(0x60) |
||
| 1454 |
// Selector of `log(bool,uint256,address)`. |
||
| 1455 |
mstore(0x00, 0x088ef9d2) |
||
| 1456 |
mstore(0x20, p0) |
||
| 1457 |
mstore(0x40, p1) |
||
| 1458 |
mstore(0x60, p2) |
||
| 1459 |
} |
||
| 1460 |
_sendLogPayload(0x1c, 0x64); |
||
| 1461 |
/// @solidity memory-safe-assembly |
||
| 1462 |
assembly {
|
||
| 1463 |
mstore(0x00, m0) |
||
| 1464 |
mstore(0x20, m1) |
||
| 1465 |
mstore(0x40, m2) |
||
| 1466 |
mstore(0x60, m3) |
||
| 1467 |
} |
||
| 1468 |
} |
||
| 1469 | |||
| 1470 |
function log(bool p0, uint256 p1, bool p2) internal pure {
|
||
| 1471 |
bytes32 m0; |
||
| 1472 |
bytes32 m1; |
||
| 1473 |
bytes32 m2; |
||
| 1474 |
bytes32 m3; |
||
| 1475 |
/// @solidity memory-safe-assembly |
||
| 1476 |
assembly {
|
||
| 1477 |
m0 := mload(0x00) |
||
| 1478 |
m1 := mload(0x20) |
||
| 1479 |
m2 := mload(0x40) |
||
| 1480 |
m3 := mload(0x60) |
||
| 1481 |
// Selector of `log(bool,uint256,bool)`. |
||
| 1482 |
mstore(0x00, 0xe8defba9) |
||
| 1483 |
mstore(0x20, p0) |
||
| 1484 |
mstore(0x40, p1) |
||
| 1485 |
mstore(0x60, p2) |
||
| 1486 |
} |
||
| 1487 |
_sendLogPayload(0x1c, 0x64); |
||
| 1488 |
/// @solidity memory-safe-assembly |
||
| 1489 |
assembly {
|
||
| 1490 |
mstore(0x00, m0) |
||
| 1491 |
mstore(0x20, m1) |
||
| 1492 |
mstore(0x40, m2) |
||
| 1493 |
mstore(0x60, m3) |
||
| 1494 |
} |
||
| 1495 |
} |
||
| 1496 | |||
| 1497 |
function log(bool p0, uint256 p1, uint256 p2) internal pure {
|
||
| 1498 |
bytes32 m0; |
||
| 1499 |
bytes32 m1; |
||
| 1500 |
bytes32 m2; |
||
| 1501 |
bytes32 m3; |
||
| 1502 |
/// @solidity memory-safe-assembly |
||
| 1503 |
assembly {
|
||
| 1504 |
m0 := mload(0x00) |
||
| 1505 |
m1 := mload(0x20) |
||
| 1506 |
m2 := mload(0x40) |
||
| 1507 |
m3 := mload(0x60) |
||
| 1508 |
// Selector of `log(bool,uint256,uint256)`. |
||
| 1509 |
mstore(0x00, 0x37103367) |
||
| 1510 |
mstore(0x20, p0) |
||
| 1511 |
mstore(0x40, p1) |
||
| 1512 |
mstore(0x60, p2) |
||
| 1513 |
} |
||
| 1514 |
_sendLogPayload(0x1c, 0x64); |
||
| 1515 |
/// @solidity memory-safe-assembly |
||
| 1516 |
assembly {
|
||
| 1517 |
mstore(0x00, m0) |
||
| 1518 |
mstore(0x20, m1) |
||
| 1519 |
mstore(0x40, m2) |
||
| 1520 |
mstore(0x60, m3) |
||
| 1521 |
} |
||
| 1522 |
} |
||
| 1523 | |||
| 1524 |
function log(bool p0, uint256 p1, bytes32 p2) internal pure {
|
||
| 1525 |
bytes32 m0; |
||
| 1526 |
bytes32 m1; |
||
| 1527 |
bytes32 m2; |
||
| 1528 |
bytes32 m3; |
||
| 1529 |
bytes32 m4; |
||
| 1530 |
bytes32 m5; |
||
| 1531 |
/// @solidity memory-safe-assembly |
||
| 1532 |
assembly {
|
||
| 1533 |
function writeString(pos, w) {
|
||
| 1534 |
let length := 0 |
||
| 1535 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1536 |
mstore(pos, length) |
||
| 1537 |
let shift := sub(256, shl(3, length)) |
||
| 1538 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1539 |
} |
||
| 1540 |
m0 := mload(0x00) |
||
| 1541 |
m1 := mload(0x20) |
||
| 1542 |
m2 := mload(0x40) |
||
| 1543 |
m3 := mload(0x60) |
||
| 1544 |
m4 := mload(0x80) |
||
| 1545 |
m5 := mload(0xa0) |
||
| 1546 |
// Selector of `log(bool,uint256,string)`. |
||
| 1547 |
mstore(0x00, 0xc3fc3970) |
||
| 1548 |
mstore(0x20, p0) |
||
| 1549 |
mstore(0x40, p1) |
||
| 1550 |
mstore(0x60, 0x60) |
||
| 1551 |
writeString(0x80, p2) |
||
| 1552 |
} |
||
| 1553 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1554 |
/// @solidity memory-safe-assembly |
||
| 1555 |
assembly {
|
||
| 1556 |
mstore(0x00, m0) |
||
| 1557 |
mstore(0x20, m1) |
||
| 1558 |
mstore(0x40, m2) |
||
| 1559 |
mstore(0x60, m3) |
||
| 1560 |
mstore(0x80, m4) |
||
| 1561 |
mstore(0xa0, m5) |
||
| 1562 |
} |
||
| 1563 |
} |
||
| 1564 | |||
| 1565 |
function log(bool p0, bytes32 p1, address p2) internal pure {
|
||
| 1566 |
bytes32 m0; |
||
| 1567 |
bytes32 m1; |
||
| 1568 |
bytes32 m2; |
||
| 1569 |
bytes32 m3; |
||
| 1570 |
bytes32 m4; |
||
| 1571 |
bytes32 m5; |
||
| 1572 |
/// @solidity memory-safe-assembly |
||
| 1573 |
assembly {
|
||
| 1574 |
function writeString(pos, w) {
|
||
| 1575 |
let length := 0 |
||
| 1576 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1577 |
mstore(pos, length) |
||
| 1578 |
let shift := sub(256, shl(3, length)) |
||
| 1579 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1580 |
} |
||
| 1581 |
m0 := mload(0x00) |
||
| 1582 |
m1 := mload(0x20) |
||
| 1583 |
m2 := mload(0x40) |
||
| 1584 |
m3 := mload(0x60) |
||
| 1585 |
m4 := mload(0x80) |
||
| 1586 |
m5 := mload(0xa0) |
||
| 1587 |
// Selector of `log(bool,string,address)`. |
||
| 1588 |
mstore(0x00, 0x9591b953) |
||
| 1589 |
mstore(0x20, p0) |
||
| 1590 |
mstore(0x40, 0x60) |
||
| 1591 |
mstore(0x60, p2) |
||
| 1592 |
writeString(0x80, p1) |
||
| 1593 |
} |
||
| 1594 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1595 |
/// @solidity memory-safe-assembly |
||
| 1596 |
assembly {
|
||
| 1597 |
mstore(0x00, m0) |
||
| 1598 |
mstore(0x20, m1) |
||
| 1599 |
mstore(0x40, m2) |
||
| 1600 |
mstore(0x60, m3) |
||
| 1601 |
mstore(0x80, m4) |
||
| 1602 |
mstore(0xa0, m5) |
||
| 1603 |
} |
||
| 1604 |
} |
||
| 1605 | |||
| 1606 |
function log(bool p0, bytes32 p1, bool p2) internal pure {
|
||
| 1607 |
bytes32 m0; |
||
| 1608 |
bytes32 m1; |
||
| 1609 |
bytes32 m2; |
||
| 1610 |
bytes32 m3; |
||
| 1611 |
bytes32 m4; |
||
| 1612 |
bytes32 m5; |
||
| 1613 |
/// @solidity memory-safe-assembly |
||
| 1614 |
assembly {
|
||
| 1615 |
function writeString(pos, w) {
|
||
| 1616 |
let length := 0 |
||
| 1617 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1618 |
mstore(pos, length) |
||
| 1619 |
let shift := sub(256, shl(3, length)) |
||
| 1620 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1621 |
} |
||
| 1622 |
m0 := mload(0x00) |
||
| 1623 |
m1 := mload(0x20) |
||
| 1624 |
m2 := mload(0x40) |
||
| 1625 |
m3 := mload(0x60) |
||
| 1626 |
m4 := mload(0x80) |
||
| 1627 |
m5 := mload(0xa0) |
||
| 1628 |
// Selector of `log(bool,string,bool)`. |
||
| 1629 |
mstore(0x00, 0xdbb4c247) |
||
| 1630 |
mstore(0x20, p0) |
||
| 1631 |
mstore(0x40, 0x60) |
||
| 1632 |
mstore(0x60, p2) |
||
| 1633 |
writeString(0x80, p1) |
||
| 1634 |
} |
||
| 1635 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1636 |
/// @solidity memory-safe-assembly |
||
| 1637 |
assembly {
|
||
| 1638 |
mstore(0x00, m0) |
||
| 1639 |
mstore(0x20, m1) |
||
| 1640 |
mstore(0x40, m2) |
||
| 1641 |
mstore(0x60, m3) |
||
| 1642 |
mstore(0x80, m4) |
||
| 1643 |
mstore(0xa0, m5) |
||
| 1644 |
} |
||
| 1645 |
} |
||
| 1646 | |||
| 1647 |
function log(bool p0, bytes32 p1, uint256 p2) internal pure {
|
||
| 1648 |
bytes32 m0; |
||
| 1649 |
bytes32 m1; |
||
| 1650 |
bytes32 m2; |
||
| 1651 |
bytes32 m3; |
||
| 1652 |
bytes32 m4; |
||
| 1653 |
bytes32 m5; |
||
| 1654 |
/// @solidity memory-safe-assembly |
||
| 1655 |
assembly {
|
||
| 1656 |
function writeString(pos, w) {
|
||
| 1657 |
let length := 0 |
||
| 1658 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1659 |
mstore(pos, length) |
||
| 1660 |
let shift := sub(256, shl(3, length)) |
||
| 1661 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1662 |
} |
||
| 1663 |
m0 := mload(0x00) |
||
| 1664 |
m1 := mload(0x20) |
||
| 1665 |
m2 := mload(0x40) |
||
| 1666 |
m3 := mload(0x60) |
||
| 1667 |
m4 := mload(0x80) |
||
| 1668 |
m5 := mload(0xa0) |
||
| 1669 |
// Selector of `log(bool,string,uint256)`. |
||
| 1670 |
mstore(0x00, 0x1093ee11) |
||
| 1671 |
mstore(0x20, p0) |
||
| 1672 |
mstore(0x40, 0x60) |
||
| 1673 |
mstore(0x60, p2) |
||
| 1674 |
writeString(0x80, p1) |
||
| 1675 |
} |
||
| 1676 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1677 |
/// @solidity memory-safe-assembly |
||
| 1678 |
assembly {
|
||
| 1679 |
mstore(0x00, m0) |
||
| 1680 |
mstore(0x20, m1) |
||
| 1681 |
mstore(0x40, m2) |
||
| 1682 |
mstore(0x60, m3) |
||
| 1683 |
mstore(0x80, m4) |
||
| 1684 |
mstore(0xa0, m5) |
||
| 1685 |
} |
||
| 1686 |
} |
||
| 1687 | |||
| 1688 |
function log(bool p0, bytes32 p1, bytes32 p2) internal pure {
|
||
| 1689 |
bytes32 m0; |
||
| 1690 |
bytes32 m1; |
||
| 1691 |
bytes32 m2; |
||
| 1692 |
bytes32 m3; |
||
| 1693 |
bytes32 m4; |
||
| 1694 |
bytes32 m5; |
||
| 1695 |
bytes32 m6; |
||
| 1696 |
bytes32 m7; |
||
| 1697 |
/// @solidity memory-safe-assembly |
||
| 1698 |
assembly {
|
||
| 1699 |
function writeString(pos, w) {
|
||
| 1700 |
let length := 0 |
||
| 1701 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1702 |
mstore(pos, length) |
||
| 1703 |
let shift := sub(256, shl(3, length)) |
||
| 1704 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1705 |
} |
||
| 1706 |
m0 := mload(0x00) |
||
| 1707 |
m1 := mload(0x20) |
||
| 1708 |
m2 := mload(0x40) |
||
| 1709 |
m3 := mload(0x60) |
||
| 1710 |
m4 := mload(0x80) |
||
| 1711 |
m5 := mload(0xa0) |
||
| 1712 |
m6 := mload(0xc0) |
||
| 1713 |
m7 := mload(0xe0) |
||
| 1714 |
// Selector of `log(bool,string,string)`. |
||
| 1715 |
mstore(0x00, 0xb076847f) |
||
| 1716 |
mstore(0x20, p0) |
||
| 1717 |
mstore(0x40, 0x60) |
||
| 1718 |
mstore(0x60, 0xa0) |
||
| 1719 |
writeString(0x80, p1) |
||
| 1720 |
writeString(0xc0, p2) |
||
| 1721 |
} |
||
| 1722 |
_sendLogPayload(0x1c, 0xe4); |
||
| 1723 |
/// @solidity memory-safe-assembly |
||
| 1724 |
assembly {
|
||
| 1725 |
mstore(0x00, m0) |
||
| 1726 |
mstore(0x20, m1) |
||
| 1727 |
mstore(0x40, m2) |
||
| 1728 |
mstore(0x60, m3) |
||
| 1729 |
mstore(0x80, m4) |
||
| 1730 |
mstore(0xa0, m5) |
||
| 1731 |
mstore(0xc0, m6) |
||
| 1732 |
mstore(0xe0, m7) |
||
| 1733 |
} |
||
| 1734 |
} |
||
| 1735 | |||
| 1736 |
function log(uint256 p0, address p1, address p2) internal pure {
|
||
| 1737 |
bytes32 m0; |
||
| 1738 |
bytes32 m1; |
||
| 1739 |
bytes32 m2; |
||
| 1740 |
bytes32 m3; |
||
| 1741 |
/// @solidity memory-safe-assembly |
||
| 1742 |
assembly {
|
||
| 1743 |
m0 := mload(0x00) |
||
| 1744 |
m1 := mload(0x20) |
||
| 1745 |
m2 := mload(0x40) |
||
| 1746 |
m3 := mload(0x60) |
||
| 1747 |
// Selector of `log(uint256,address,address)`. |
||
| 1748 |
mstore(0x00, 0xbcfd9be0) |
||
| 1749 |
mstore(0x20, p0) |
||
| 1750 |
mstore(0x40, p1) |
||
| 1751 |
mstore(0x60, p2) |
||
| 1752 |
} |
||
| 1753 |
_sendLogPayload(0x1c, 0x64); |
||
| 1754 |
/// @solidity memory-safe-assembly |
||
| 1755 |
assembly {
|
||
| 1756 |
mstore(0x00, m0) |
||
| 1757 |
mstore(0x20, m1) |
||
| 1758 |
mstore(0x40, m2) |
||
| 1759 |
mstore(0x60, m3) |
||
| 1760 |
} |
||
| 1761 |
} |
||
| 1762 | |||
| 1763 |
function log(uint256 p0, address p1, bool p2) internal pure {
|
||
| 1764 |
bytes32 m0; |
||
| 1765 |
bytes32 m1; |
||
| 1766 |
bytes32 m2; |
||
| 1767 |
bytes32 m3; |
||
| 1768 |
/// @solidity memory-safe-assembly |
||
| 1769 |
assembly {
|
||
| 1770 |
m0 := mload(0x00) |
||
| 1771 |
m1 := mload(0x20) |
||
| 1772 |
m2 := mload(0x40) |
||
| 1773 |
m3 := mload(0x60) |
||
| 1774 |
// Selector of `log(uint256,address,bool)`. |
||
| 1775 |
mstore(0x00, 0x9b6ec042) |
||
| 1776 |
mstore(0x20, p0) |
||
| 1777 |
mstore(0x40, p1) |
||
| 1778 |
mstore(0x60, p2) |
||
| 1779 |
} |
||
| 1780 |
_sendLogPayload(0x1c, 0x64); |
||
| 1781 |
/// @solidity memory-safe-assembly |
||
| 1782 |
assembly {
|
||
| 1783 |
mstore(0x00, m0) |
||
| 1784 |
mstore(0x20, m1) |
||
| 1785 |
mstore(0x40, m2) |
||
| 1786 |
mstore(0x60, m3) |
||
| 1787 |
} |
||
| 1788 |
} |
||
| 1789 | |||
| 1790 |
function log(uint256 p0, address p1, uint256 p2) internal pure {
|
||
| 1791 |
bytes32 m0; |
||
| 1792 |
bytes32 m1; |
||
| 1793 |
bytes32 m2; |
||
| 1794 |
bytes32 m3; |
||
| 1795 |
/// @solidity memory-safe-assembly |
||
| 1796 |
assembly {
|
||
| 1797 |
m0 := mload(0x00) |
||
| 1798 |
m1 := mload(0x20) |
||
| 1799 |
m2 := mload(0x40) |
||
| 1800 |
m3 := mload(0x60) |
||
| 1801 |
// Selector of `log(uint256,address,uint256)`. |
||
| 1802 |
mstore(0x00, 0x5a9b5ed5) |
||
| 1803 |
mstore(0x20, p0) |
||
| 1804 |
mstore(0x40, p1) |
||
| 1805 |
mstore(0x60, p2) |
||
| 1806 |
} |
||
| 1807 |
_sendLogPayload(0x1c, 0x64); |
||
| 1808 |
/// @solidity memory-safe-assembly |
||
| 1809 |
assembly {
|
||
| 1810 |
mstore(0x00, m0) |
||
| 1811 |
mstore(0x20, m1) |
||
| 1812 |
mstore(0x40, m2) |
||
| 1813 |
mstore(0x60, m3) |
||
| 1814 |
} |
||
| 1815 |
} |
||
| 1816 | |||
| 1817 |
function log(uint256 p0, address p1, bytes32 p2) internal pure {
|
||
| 1818 |
bytes32 m0; |
||
| 1819 |
bytes32 m1; |
||
| 1820 |
bytes32 m2; |
||
| 1821 |
bytes32 m3; |
||
| 1822 |
bytes32 m4; |
||
| 1823 |
bytes32 m5; |
||
| 1824 |
/// @solidity memory-safe-assembly |
||
| 1825 |
assembly {
|
||
| 1826 |
function writeString(pos, w) {
|
||
| 1827 |
let length := 0 |
||
| 1828 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1829 |
mstore(pos, length) |
||
| 1830 |
let shift := sub(256, shl(3, length)) |
||
| 1831 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1832 |
} |
||
| 1833 |
m0 := mload(0x00) |
||
| 1834 |
m1 := mload(0x20) |
||
| 1835 |
m2 := mload(0x40) |
||
| 1836 |
m3 := mload(0x60) |
||
| 1837 |
m4 := mload(0x80) |
||
| 1838 |
m5 := mload(0xa0) |
||
| 1839 |
// Selector of `log(uint256,address,string)`. |
||
| 1840 |
mstore(0x00, 0x63cb41f9) |
||
| 1841 |
mstore(0x20, p0) |
||
| 1842 |
mstore(0x40, p1) |
||
| 1843 |
mstore(0x60, 0x60) |
||
| 1844 |
writeString(0x80, p2) |
||
| 1845 |
} |
||
| 1846 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1847 |
/// @solidity memory-safe-assembly |
||
| 1848 |
assembly {
|
||
| 1849 |
mstore(0x00, m0) |
||
| 1850 |
mstore(0x20, m1) |
||
| 1851 |
mstore(0x40, m2) |
||
| 1852 |
mstore(0x60, m3) |
||
| 1853 |
mstore(0x80, m4) |
||
| 1854 |
mstore(0xa0, m5) |
||
| 1855 |
} |
||
| 1856 |
} |
||
| 1857 | |||
| 1858 |
function log(uint256 p0, bool p1, address p2) internal pure {
|
||
| 1859 |
bytes32 m0; |
||
| 1860 |
bytes32 m1; |
||
| 1861 |
bytes32 m2; |
||
| 1862 |
bytes32 m3; |
||
| 1863 |
/// @solidity memory-safe-assembly |
||
| 1864 |
assembly {
|
||
| 1865 |
m0 := mload(0x00) |
||
| 1866 |
m1 := mload(0x20) |
||
| 1867 |
m2 := mload(0x40) |
||
| 1868 |
m3 := mload(0x60) |
||
| 1869 |
// Selector of `log(uint256,bool,address)`. |
||
| 1870 |
mstore(0x00, 0x35085f7b) |
||
| 1871 |
mstore(0x20, p0) |
||
| 1872 |
mstore(0x40, p1) |
||
| 1873 |
mstore(0x60, p2) |
||
| 1874 |
} |
||
| 1875 |
_sendLogPayload(0x1c, 0x64); |
||
| 1876 |
/// @solidity memory-safe-assembly |
||
| 1877 |
assembly {
|
||
| 1878 |
mstore(0x00, m0) |
||
| 1879 |
mstore(0x20, m1) |
||
| 1880 |
mstore(0x40, m2) |
||
| 1881 |
mstore(0x60, m3) |
||
| 1882 |
} |
||
| 1883 |
} |
||
| 1884 | |||
| 1885 |
function log(uint256 p0, bool p1, bool p2) internal pure {
|
||
| 1886 |
bytes32 m0; |
||
| 1887 |
bytes32 m1; |
||
| 1888 |
bytes32 m2; |
||
| 1889 |
bytes32 m3; |
||
| 1890 |
/// @solidity memory-safe-assembly |
||
| 1891 |
assembly {
|
||
| 1892 |
m0 := mload(0x00) |
||
| 1893 |
m1 := mload(0x20) |
||
| 1894 |
m2 := mload(0x40) |
||
| 1895 |
m3 := mload(0x60) |
||
| 1896 |
// Selector of `log(uint256,bool,bool)`. |
||
| 1897 |
mstore(0x00, 0x20718650) |
||
| 1898 |
mstore(0x20, p0) |
||
| 1899 |
mstore(0x40, p1) |
||
| 1900 |
mstore(0x60, p2) |
||
| 1901 |
} |
||
| 1902 |
_sendLogPayload(0x1c, 0x64); |
||
| 1903 |
/// @solidity memory-safe-assembly |
||
| 1904 |
assembly {
|
||
| 1905 |
mstore(0x00, m0) |
||
| 1906 |
mstore(0x20, m1) |
||
| 1907 |
mstore(0x40, m2) |
||
| 1908 |
mstore(0x60, m3) |
||
| 1909 |
} |
||
| 1910 |
} |
||
| 1911 | |||
| 1912 |
function log(uint256 p0, bool p1, uint256 p2) internal pure {
|
||
| 1913 |
bytes32 m0; |
||
| 1914 |
bytes32 m1; |
||
| 1915 |
bytes32 m2; |
||
| 1916 |
bytes32 m3; |
||
| 1917 |
/// @solidity memory-safe-assembly |
||
| 1918 |
assembly {
|
||
| 1919 |
m0 := mload(0x00) |
||
| 1920 |
m1 := mload(0x20) |
||
| 1921 |
m2 := mload(0x40) |
||
| 1922 |
m3 := mload(0x60) |
||
| 1923 |
// Selector of `log(uint256,bool,uint256)`. |
||
| 1924 |
mstore(0x00, 0x20098014) |
||
| 1925 |
mstore(0x20, p0) |
||
| 1926 |
mstore(0x40, p1) |
||
| 1927 |
mstore(0x60, p2) |
||
| 1928 |
} |
||
| 1929 |
_sendLogPayload(0x1c, 0x64); |
||
| 1930 |
/// @solidity memory-safe-assembly |
||
| 1931 |
assembly {
|
||
| 1932 |
mstore(0x00, m0) |
||
| 1933 |
mstore(0x20, m1) |
||
| 1934 |
mstore(0x40, m2) |
||
| 1935 |
mstore(0x60, m3) |
||
| 1936 |
} |
||
| 1937 |
} |
||
| 1938 | |||
| 1939 |
function log(uint256 p0, bool p1, bytes32 p2) internal pure {
|
||
| 1940 |
bytes32 m0; |
||
| 1941 |
bytes32 m1; |
||
| 1942 |
bytes32 m2; |
||
| 1943 |
bytes32 m3; |
||
| 1944 |
bytes32 m4; |
||
| 1945 |
bytes32 m5; |
||
| 1946 |
/// @solidity memory-safe-assembly |
||
| 1947 |
assembly {
|
||
| 1948 |
function writeString(pos, w) {
|
||
| 1949 |
let length := 0 |
||
| 1950 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 1951 |
mstore(pos, length) |
||
| 1952 |
let shift := sub(256, shl(3, length)) |
||
| 1953 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 1954 |
} |
||
| 1955 |
m0 := mload(0x00) |
||
| 1956 |
m1 := mload(0x20) |
||
| 1957 |
m2 := mload(0x40) |
||
| 1958 |
m3 := mload(0x60) |
||
| 1959 |
m4 := mload(0x80) |
||
| 1960 |
m5 := mload(0xa0) |
||
| 1961 |
// Selector of `log(uint256,bool,string)`. |
||
| 1962 |
mstore(0x00, 0x85775021) |
||
| 1963 |
mstore(0x20, p0) |
||
| 1964 |
mstore(0x40, p1) |
||
| 1965 |
mstore(0x60, 0x60) |
||
| 1966 |
writeString(0x80, p2) |
||
| 1967 |
} |
||
| 1968 |
_sendLogPayload(0x1c, 0xa4); |
||
| 1969 |
/// @solidity memory-safe-assembly |
||
| 1970 |
assembly {
|
||
| 1971 |
mstore(0x00, m0) |
||
| 1972 |
mstore(0x20, m1) |
||
| 1973 |
mstore(0x40, m2) |
||
| 1974 |
mstore(0x60, m3) |
||
| 1975 |
mstore(0x80, m4) |
||
| 1976 |
mstore(0xa0, m5) |
||
| 1977 |
} |
||
| 1978 |
} |
||
| 1979 | |||
| 1980 |
function log(uint256 p0, uint256 p1, address p2) internal pure {
|
||
| 1981 |
bytes32 m0; |
||
| 1982 |
bytes32 m1; |
||
| 1983 |
bytes32 m2; |
||
| 1984 |
bytes32 m3; |
||
| 1985 |
/// @solidity memory-safe-assembly |
||
| 1986 |
assembly {
|
||
| 1987 |
m0 := mload(0x00) |
||
| 1988 |
m1 := mload(0x20) |
||
| 1989 |
m2 := mload(0x40) |
||
| 1990 |
m3 := mload(0x60) |
||
| 1991 |
// Selector of `log(uint256,uint256,address)`. |
||
| 1992 |
mstore(0x00, 0x5c96b331) |
||
| 1993 |
mstore(0x20, p0) |
||
| 1994 |
mstore(0x40, p1) |
||
| 1995 |
mstore(0x60, p2) |
||
| 1996 |
} |
||
| 1997 |
_sendLogPayload(0x1c, 0x64); |
||
| 1998 |
/// @solidity memory-safe-assembly |
||
| 1999 |
assembly {
|
||
| 2000 |
mstore(0x00, m0) |
||
| 2001 |
mstore(0x20, m1) |
||
| 2002 |
mstore(0x40, m2) |
||
| 2003 |
mstore(0x60, m3) |
||
| 2004 |
} |
||
| 2005 |
} |
||
| 2006 | |||
| 2007 |
function log(uint256 p0, uint256 p1, bool p2) internal pure {
|
||
| 2008 |
bytes32 m0; |
||
| 2009 |
bytes32 m1; |
||
| 2010 |
bytes32 m2; |
||
| 2011 |
bytes32 m3; |
||
| 2012 |
/// @solidity memory-safe-assembly |
||
| 2013 |
assembly {
|
||
| 2014 |
m0 := mload(0x00) |
||
| 2015 |
m1 := mload(0x20) |
||
| 2016 |
m2 := mload(0x40) |
||
| 2017 |
m3 := mload(0x60) |
||
| 2018 |
// Selector of `log(uint256,uint256,bool)`. |
||
| 2019 |
mstore(0x00, 0x4766da72) |
||
| 2020 |
mstore(0x20, p0) |
||
| 2021 |
mstore(0x40, p1) |
||
| 2022 |
mstore(0x60, p2) |
||
| 2023 |
} |
||
| 2024 |
_sendLogPayload(0x1c, 0x64); |
||
| 2025 |
/// @solidity memory-safe-assembly |
||
| 2026 |
assembly {
|
||
| 2027 |
mstore(0x00, m0) |
||
| 2028 |
mstore(0x20, m1) |
||
| 2029 |
mstore(0x40, m2) |
||
| 2030 |
mstore(0x60, m3) |
||
| 2031 |
} |
||
| 2032 |
} |
||
| 2033 | |||
| 2034 |
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
|
||
| 2035 |
bytes32 m0; |
||
| 2036 |
bytes32 m1; |
||
| 2037 |
bytes32 m2; |
||
| 2038 |
bytes32 m3; |
||
| 2039 |
/// @solidity memory-safe-assembly |
||
| 2040 |
assembly {
|
||
| 2041 |
m0 := mload(0x00) |
||
| 2042 |
m1 := mload(0x20) |
||
| 2043 |
m2 := mload(0x40) |
||
| 2044 |
m3 := mload(0x60) |
||
| 2045 |
// Selector of `log(uint256,uint256,uint256)`. |
||
| 2046 |
mstore(0x00, 0xd1ed7a3c) |
||
| 2047 |
mstore(0x20, p0) |
||
| 2048 |
mstore(0x40, p1) |
||
| 2049 |
mstore(0x60, p2) |
||
| 2050 |
} |
||
| 2051 |
_sendLogPayload(0x1c, 0x64); |
||
| 2052 |
/// @solidity memory-safe-assembly |
||
| 2053 |
assembly {
|
||
| 2054 |
mstore(0x00, m0) |
||
| 2055 |
mstore(0x20, m1) |
||
| 2056 |
mstore(0x40, m2) |
||
| 2057 |
mstore(0x60, m3) |
||
| 2058 |
} |
||
| 2059 |
} |
||
| 2060 | |||
| 2061 |
function log(uint256 p0, uint256 p1, bytes32 p2) internal pure {
|
||
| 2062 |
bytes32 m0; |
||
| 2063 |
bytes32 m1; |
||
| 2064 |
bytes32 m2; |
||
| 2065 |
bytes32 m3; |
||
| 2066 |
bytes32 m4; |
||
| 2067 |
bytes32 m5; |
||
| 2068 |
/// @solidity memory-safe-assembly |
||
| 2069 |
assembly {
|
||
| 2070 |
function writeString(pos, w) {
|
||
| 2071 |
let length := 0 |
||
| 2072 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2073 |
mstore(pos, length) |
||
| 2074 |
let shift := sub(256, shl(3, length)) |
||
| 2075 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2076 |
} |
||
| 2077 |
m0 := mload(0x00) |
||
| 2078 |
m1 := mload(0x20) |
||
| 2079 |
m2 := mload(0x40) |
||
| 2080 |
m3 := mload(0x60) |
||
| 2081 |
m4 := mload(0x80) |
||
| 2082 |
m5 := mload(0xa0) |
||
| 2083 |
// Selector of `log(uint256,uint256,string)`. |
||
| 2084 |
mstore(0x00, 0x71d04af2) |
||
| 2085 |
mstore(0x20, p0) |
||
| 2086 |
mstore(0x40, p1) |
||
| 2087 |
mstore(0x60, 0x60) |
||
| 2088 |
writeString(0x80, p2) |
||
| 2089 |
} |
||
| 2090 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2091 |
/// @solidity memory-safe-assembly |
||
| 2092 |
assembly {
|
||
| 2093 |
mstore(0x00, m0) |
||
| 2094 |
mstore(0x20, m1) |
||
| 2095 |
mstore(0x40, m2) |
||
| 2096 |
mstore(0x60, m3) |
||
| 2097 |
mstore(0x80, m4) |
||
| 2098 |
mstore(0xa0, m5) |
||
| 2099 |
} |
||
| 2100 |
} |
||
| 2101 | |||
| 2102 |
function log(uint256 p0, bytes32 p1, address p2) internal pure {
|
||
| 2103 |
bytes32 m0; |
||
| 2104 |
bytes32 m1; |
||
| 2105 |
bytes32 m2; |
||
| 2106 |
bytes32 m3; |
||
| 2107 |
bytes32 m4; |
||
| 2108 |
bytes32 m5; |
||
| 2109 |
/// @solidity memory-safe-assembly |
||
| 2110 |
assembly {
|
||
| 2111 |
function writeString(pos, w) {
|
||
| 2112 |
let length := 0 |
||
| 2113 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2114 |
mstore(pos, length) |
||
| 2115 |
let shift := sub(256, shl(3, length)) |
||
| 2116 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2117 |
} |
||
| 2118 |
m0 := mload(0x00) |
||
| 2119 |
m1 := mload(0x20) |
||
| 2120 |
m2 := mload(0x40) |
||
| 2121 |
m3 := mload(0x60) |
||
| 2122 |
m4 := mload(0x80) |
||
| 2123 |
m5 := mload(0xa0) |
||
| 2124 |
// Selector of `log(uint256,string,address)`. |
||
| 2125 |
mstore(0x00, 0x7afac959) |
||
| 2126 |
mstore(0x20, p0) |
||
| 2127 |
mstore(0x40, 0x60) |
||
| 2128 |
mstore(0x60, p2) |
||
| 2129 |
writeString(0x80, p1) |
||
| 2130 |
} |
||
| 2131 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2132 |
/// @solidity memory-safe-assembly |
||
| 2133 |
assembly {
|
||
| 2134 |
mstore(0x00, m0) |
||
| 2135 |
mstore(0x20, m1) |
||
| 2136 |
mstore(0x40, m2) |
||
| 2137 |
mstore(0x60, m3) |
||
| 2138 |
mstore(0x80, m4) |
||
| 2139 |
mstore(0xa0, m5) |
||
| 2140 |
} |
||
| 2141 |
} |
||
| 2142 | |||
| 2143 |
function log(uint256 p0, bytes32 p1, bool p2) internal pure {
|
||
| 2144 |
bytes32 m0; |
||
| 2145 |
bytes32 m1; |
||
| 2146 |
bytes32 m2; |
||
| 2147 |
bytes32 m3; |
||
| 2148 |
bytes32 m4; |
||
| 2149 |
bytes32 m5; |
||
| 2150 |
/// @solidity memory-safe-assembly |
||
| 2151 |
assembly {
|
||
| 2152 |
function writeString(pos, w) {
|
||
| 2153 |
let length := 0 |
||
| 2154 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2155 |
mstore(pos, length) |
||
| 2156 |
let shift := sub(256, shl(3, length)) |
||
| 2157 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2158 |
} |
||
| 2159 |
m0 := mload(0x00) |
||
| 2160 |
m1 := mload(0x20) |
||
| 2161 |
m2 := mload(0x40) |
||
| 2162 |
m3 := mload(0x60) |
||
| 2163 |
m4 := mload(0x80) |
||
| 2164 |
m5 := mload(0xa0) |
||
| 2165 |
// Selector of `log(uint256,string,bool)`. |
||
| 2166 |
mstore(0x00, 0x4ceda75a) |
||
| 2167 |
mstore(0x20, p0) |
||
| 2168 |
mstore(0x40, 0x60) |
||
| 2169 |
mstore(0x60, p2) |
||
| 2170 |
writeString(0x80, p1) |
||
| 2171 |
} |
||
| 2172 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2173 |
/// @solidity memory-safe-assembly |
||
| 2174 |
assembly {
|
||
| 2175 |
mstore(0x00, m0) |
||
| 2176 |
mstore(0x20, m1) |
||
| 2177 |
mstore(0x40, m2) |
||
| 2178 |
mstore(0x60, m3) |
||
| 2179 |
mstore(0x80, m4) |
||
| 2180 |
mstore(0xa0, m5) |
||
| 2181 |
} |
||
| 2182 |
} |
||
| 2183 | |||
| 2184 |
function log(uint256 p0, bytes32 p1, uint256 p2) internal pure {
|
||
| 2185 |
bytes32 m0; |
||
| 2186 |
bytes32 m1; |
||
| 2187 |
bytes32 m2; |
||
| 2188 |
bytes32 m3; |
||
| 2189 |
bytes32 m4; |
||
| 2190 |
bytes32 m5; |
||
| 2191 |
/// @solidity memory-safe-assembly |
||
| 2192 |
assembly {
|
||
| 2193 |
function writeString(pos, w) {
|
||
| 2194 |
let length := 0 |
||
| 2195 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2196 |
mstore(pos, length) |
||
| 2197 |
let shift := sub(256, shl(3, length)) |
||
| 2198 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2199 |
} |
||
| 2200 |
m0 := mload(0x00) |
||
| 2201 |
m1 := mload(0x20) |
||
| 2202 |
m2 := mload(0x40) |
||
| 2203 |
m3 := mload(0x60) |
||
| 2204 |
m4 := mload(0x80) |
||
| 2205 |
m5 := mload(0xa0) |
||
| 2206 |
// Selector of `log(uint256,string,uint256)`. |
||
| 2207 |
mstore(0x00, 0x37aa7d4c) |
||
| 2208 |
mstore(0x20, p0) |
||
| 2209 |
mstore(0x40, 0x60) |
||
| 2210 |
mstore(0x60, p2) |
||
| 2211 |
writeString(0x80, p1) |
||
| 2212 |
} |
||
| 2213 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2214 |
/// @solidity memory-safe-assembly |
||
| 2215 |
assembly {
|
||
| 2216 |
mstore(0x00, m0) |
||
| 2217 |
mstore(0x20, m1) |
||
| 2218 |
mstore(0x40, m2) |
||
| 2219 |
mstore(0x60, m3) |
||
| 2220 |
mstore(0x80, m4) |
||
| 2221 |
mstore(0xa0, m5) |
||
| 2222 |
} |
||
| 2223 |
} |
||
| 2224 | |||
| 2225 |
function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure {
|
||
| 2226 |
bytes32 m0; |
||
| 2227 |
bytes32 m1; |
||
| 2228 |
bytes32 m2; |
||
| 2229 |
bytes32 m3; |
||
| 2230 |
bytes32 m4; |
||
| 2231 |
bytes32 m5; |
||
| 2232 |
bytes32 m6; |
||
| 2233 |
bytes32 m7; |
||
| 2234 |
/// @solidity memory-safe-assembly |
||
| 2235 |
assembly {
|
||
| 2236 |
function writeString(pos, w) {
|
||
| 2237 |
let length := 0 |
||
| 2238 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2239 |
mstore(pos, length) |
||
| 2240 |
let shift := sub(256, shl(3, length)) |
||
| 2241 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2242 |
} |
||
| 2243 |
m0 := mload(0x00) |
||
| 2244 |
m1 := mload(0x20) |
||
| 2245 |
m2 := mload(0x40) |
||
| 2246 |
m3 := mload(0x60) |
||
| 2247 |
m4 := mload(0x80) |
||
| 2248 |
m5 := mload(0xa0) |
||
| 2249 |
m6 := mload(0xc0) |
||
| 2250 |
m7 := mload(0xe0) |
||
| 2251 |
// Selector of `log(uint256,string,string)`. |
||
| 2252 |
mstore(0x00, 0xb115611f) |
||
| 2253 |
mstore(0x20, p0) |
||
| 2254 |
mstore(0x40, 0x60) |
||
| 2255 |
mstore(0x60, 0xa0) |
||
| 2256 |
writeString(0x80, p1) |
||
| 2257 |
writeString(0xc0, p2) |
||
| 2258 |
} |
||
| 2259 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2260 |
/// @solidity memory-safe-assembly |
||
| 2261 |
assembly {
|
||
| 2262 |
mstore(0x00, m0) |
||
| 2263 |
mstore(0x20, m1) |
||
| 2264 |
mstore(0x40, m2) |
||
| 2265 |
mstore(0x60, m3) |
||
| 2266 |
mstore(0x80, m4) |
||
| 2267 |
mstore(0xa0, m5) |
||
| 2268 |
mstore(0xc0, m6) |
||
| 2269 |
mstore(0xe0, m7) |
||
| 2270 |
} |
||
| 2271 |
} |
||
| 2272 | |||
| 2273 |
function log(bytes32 p0, address p1, address p2) internal pure {
|
||
| 2274 |
bytes32 m0; |
||
| 2275 |
bytes32 m1; |
||
| 2276 |
bytes32 m2; |
||
| 2277 |
bytes32 m3; |
||
| 2278 |
bytes32 m4; |
||
| 2279 |
bytes32 m5; |
||
| 2280 |
/// @solidity memory-safe-assembly |
||
| 2281 |
assembly {
|
||
| 2282 |
function writeString(pos, w) {
|
||
| 2283 |
let length := 0 |
||
| 2284 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2285 |
mstore(pos, length) |
||
| 2286 |
let shift := sub(256, shl(3, length)) |
||
| 2287 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2288 |
} |
||
| 2289 |
m0 := mload(0x00) |
||
| 2290 |
m1 := mload(0x20) |
||
| 2291 |
m2 := mload(0x40) |
||
| 2292 |
m3 := mload(0x60) |
||
| 2293 |
m4 := mload(0x80) |
||
| 2294 |
m5 := mload(0xa0) |
||
| 2295 |
// Selector of `log(string,address,address)`. |
||
| 2296 |
mstore(0x00, 0xfcec75e0) |
||
| 2297 |
mstore(0x20, 0x60) |
||
| 2298 |
mstore(0x40, p1) |
||
| 2299 |
mstore(0x60, p2) |
||
| 2300 |
writeString(0x80, p0) |
||
| 2301 |
} |
||
| 2302 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2303 |
/// @solidity memory-safe-assembly |
||
| 2304 |
assembly {
|
||
| 2305 |
mstore(0x00, m0) |
||
| 2306 |
mstore(0x20, m1) |
||
| 2307 |
mstore(0x40, m2) |
||
| 2308 |
mstore(0x60, m3) |
||
| 2309 |
mstore(0x80, m4) |
||
| 2310 |
mstore(0xa0, m5) |
||
| 2311 |
} |
||
| 2312 |
} |
||
| 2313 | |||
| 2314 |
function log(bytes32 p0, address p1, bool p2) internal pure {
|
||
| 2315 |
bytes32 m0; |
||
| 2316 |
bytes32 m1; |
||
| 2317 |
bytes32 m2; |
||
| 2318 |
bytes32 m3; |
||
| 2319 |
bytes32 m4; |
||
| 2320 |
bytes32 m5; |
||
| 2321 |
/// @solidity memory-safe-assembly |
||
| 2322 |
assembly {
|
||
| 2323 |
function writeString(pos, w) {
|
||
| 2324 |
let length := 0 |
||
| 2325 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2326 |
mstore(pos, length) |
||
| 2327 |
let shift := sub(256, shl(3, length)) |
||
| 2328 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2329 |
} |
||
| 2330 |
m0 := mload(0x00) |
||
| 2331 |
m1 := mload(0x20) |
||
| 2332 |
m2 := mload(0x40) |
||
| 2333 |
m3 := mload(0x60) |
||
| 2334 |
m4 := mload(0x80) |
||
| 2335 |
m5 := mload(0xa0) |
||
| 2336 |
// Selector of `log(string,address,bool)`. |
||
| 2337 |
mstore(0x00, 0xc91d5ed4) |
||
| 2338 |
mstore(0x20, 0x60) |
||
| 2339 |
mstore(0x40, p1) |
||
| 2340 |
mstore(0x60, p2) |
||
| 2341 |
writeString(0x80, p0) |
||
| 2342 |
} |
||
| 2343 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2344 |
/// @solidity memory-safe-assembly |
||
| 2345 |
assembly {
|
||
| 2346 |
mstore(0x00, m0) |
||
| 2347 |
mstore(0x20, m1) |
||
| 2348 |
mstore(0x40, m2) |
||
| 2349 |
mstore(0x60, m3) |
||
| 2350 |
mstore(0x80, m4) |
||
| 2351 |
mstore(0xa0, m5) |
||
| 2352 |
} |
||
| 2353 |
} |
||
| 2354 | |||
| 2355 |
function log(bytes32 p0, address p1, uint256 p2) internal pure {
|
||
| 2356 |
bytes32 m0; |
||
| 2357 |
bytes32 m1; |
||
| 2358 |
bytes32 m2; |
||
| 2359 |
bytes32 m3; |
||
| 2360 |
bytes32 m4; |
||
| 2361 |
bytes32 m5; |
||
| 2362 |
/// @solidity memory-safe-assembly |
||
| 2363 |
assembly {
|
||
| 2364 |
function writeString(pos, w) {
|
||
| 2365 |
let length := 0 |
||
| 2366 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2367 |
mstore(pos, length) |
||
| 2368 |
let shift := sub(256, shl(3, length)) |
||
| 2369 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2370 |
} |
||
| 2371 |
m0 := mload(0x00) |
||
| 2372 |
m1 := mload(0x20) |
||
| 2373 |
m2 := mload(0x40) |
||
| 2374 |
m3 := mload(0x60) |
||
| 2375 |
m4 := mload(0x80) |
||
| 2376 |
m5 := mload(0xa0) |
||
| 2377 |
// Selector of `log(string,address,uint256)`. |
||
| 2378 |
mstore(0x00, 0x0d26b925) |
||
| 2379 |
mstore(0x20, 0x60) |
||
| 2380 |
mstore(0x40, p1) |
||
| 2381 |
mstore(0x60, p2) |
||
| 2382 |
writeString(0x80, p0) |
||
| 2383 |
} |
||
| 2384 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2385 |
/// @solidity memory-safe-assembly |
||
| 2386 |
assembly {
|
||
| 2387 |
mstore(0x00, m0) |
||
| 2388 |
mstore(0x20, m1) |
||
| 2389 |
mstore(0x40, m2) |
||
| 2390 |
mstore(0x60, m3) |
||
| 2391 |
mstore(0x80, m4) |
||
| 2392 |
mstore(0xa0, m5) |
||
| 2393 |
} |
||
| 2394 |
} |
||
| 2395 | |||
| 2396 |
function log(bytes32 p0, address p1, bytes32 p2) internal pure {
|
||
| 2397 |
bytes32 m0; |
||
| 2398 |
bytes32 m1; |
||
| 2399 |
bytes32 m2; |
||
| 2400 |
bytes32 m3; |
||
| 2401 |
bytes32 m4; |
||
| 2402 |
bytes32 m5; |
||
| 2403 |
bytes32 m6; |
||
| 2404 |
bytes32 m7; |
||
| 2405 |
/// @solidity memory-safe-assembly |
||
| 2406 |
assembly {
|
||
| 2407 |
function writeString(pos, w) {
|
||
| 2408 |
let length := 0 |
||
| 2409 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2410 |
mstore(pos, length) |
||
| 2411 |
let shift := sub(256, shl(3, length)) |
||
| 2412 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2413 |
} |
||
| 2414 |
m0 := mload(0x00) |
||
| 2415 |
m1 := mload(0x20) |
||
| 2416 |
m2 := mload(0x40) |
||
| 2417 |
m3 := mload(0x60) |
||
| 2418 |
m4 := mload(0x80) |
||
| 2419 |
m5 := mload(0xa0) |
||
| 2420 |
m6 := mload(0xc0) |
||
| 2421 |
m7 := mload(0xe0) |
||
| 2422 |
// Selector of `log(string,address,string)`. |
||
| 2423 |
mstore(0x00, 0xe0e9ad4f) |
||
| 2424 |
mstore(0x20, 0x60) |
||
| 2425 |
mstore(0x40, p1) |
||
| 2426 |
mstore(0x60, 0xa0) |
||
| 2427 |
writeString(0x80, p0) |
||
| 2428 |
writeString(0xc0, p2) |
||
| 2429 |
} |
||
| 2430 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2431 |
/// @solidity memory-safe-assembly |
||
| 2432 |
assembly {
|
||
| 2433 |
mstore(0x00, m0) |
||
| 2434 |
mstore(0x20, m1) |
||
| 2435 |
mstore(0x40, m2) |
||
| 2436 |
mstore(0x60, m3) |
||
| 2437 |
mstore(0x80, m4) |
||
| 2438 |
mstore(0xa0, m5) |
||
| 2439 |
mstore(0xc0, m6) |
||
| 2440 |
mstore(0xe0, m7) |
||
| 2441 |
} |
||
| 2442 |
} |
||
| 2443 | |||
| 2444 |
function log(bytes32 p0, bool p1, address p2) internal pure {
|
||
| 2445 |
bytes32 m0; |
||
| 2446 |
bytes32 m1; |
||
| 2447 |
bytes32 m2; |
||
| 2448 |
bytes32 m3; |
||
| 2449 |
bytes32 m4; |
||
| 2450 |
bytes32 m5; |
||
| 2451 |
/// @solidity memory-safe-assembly |
||
| 2452 |
assembly {
|
||
| 2453 |
function writeString(pos, w) {
|
||
| 2454 |
let length := 0 |
||
| 2455 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2456 |
mstore(pos, length) |
||
| 2457 |
let shift := sub(256, shl(3, length)) |
||
| 2458 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2459 |
} |
||
| 2460 |
m0 := mload(0x00) |
||
| 2461 |
m1 := mload(0x20) |
||
| 2462 |
m2 := mload(0x40) |
||
| 2463 |
m3 := mload(0x60) |
||
| 2464 |
m4 := mload(0x80) |
||
| 2465 |
m5 := mload(0xa0) |
||
| 2466 |
// Selector of `log(string,bool,address)`. |
||
| 2467 |
mstore(0x00, 0x932bbb38) |
||
| 2468 |
mstore(0x20, 0x60) |
||
| 2469 |
mstore(0x40, p1) |
||
| 2470 |
mstore(0x60, p2) |
||
| 2471 |
writeString(0x80, p0) |
||
| 2472 |
} |
||
| 2473 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2474 |
/// @solidity memory-safe-assembly |
||
| 2475 |
assembly {
|
||
| 2476 |
mstore(0x00, m0) |
||
| 2477 |
mstore(0x20, m1) |
||
| 2478 |
mstore(0x40, m2) |
||
| 2479 |
mstore(0x60, m3) |
||
| 2480 |
mstore(0x80, m4) |
||
| 2481 |
mstore(0xa0, m5) |
||
| 2482 |
} |
||
| 2483 |
} |
||
| 2484 | |||
| 2485 |
function log(bytes32 p0, bool p1, bool p2) internal pure {
|
||
| 2486 |
bytes32 m0; |
||
| 2487 |
bytes32 m1; |
||
| 2488 |
bytes32 m2; |
||
| 2489 |
bytes32 m3; |
||
| 2490 |
bytes32 m4; |
||
| 2491 |
bytes32 m5; |
||
| 2492 |
/// @solidity memory-safe-assembly |
||
| 2493 |
assembly {
|
||
| 2494 |
function writeString(pos, w) {
|
||
| 2495 |
let length := 0 |
||
| 2496 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2497 |
mstore(pos, length) |
||
| 2498 |
let shift := sub(256, shl(3, length)) |
||
| 2499 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2500 |
} |
||
| 2501 |
m0 := mload(0x00) |
||
| 2502 |
m1 := mload(0x20) |
||
| 2503 |
m2 := mload(0x40) |
||
| 2504 |
m3 := mload(0x60) |
||
| 2505 |
m4 := mload(0x80) |
||
| 2506 |
m5 := mload(0xa0) |
||
| 2507 |
// Selector of `log(string,bool,bool)`. |
||
| 2508 |
mstore(0x00, 0x850b7ad6) |
||
| 2509 |
mstore(0x20, 0x60) |
||
| 2510 |
mstore(0x40, p1) |
||
| 2511 |
mstore(0x60, p2) |
||
| 2512 |
writeString(0x80, p0) |
||
| 2513 |
} |
||
| 2514 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2515 |
/// @solidity memory-safe-assembly |
||
| 2516 |
assembly {
|
||
| 2517 |
mstore(0x00, m0) |
||
| 2518 |
mstore(0x20, m1) |
||
| 2519 |
mstore(0x40, m2) |
||
| 2520 |
mstore(0x60, m3) |
||
| 2521 |
mstore(0x80, m4) |
||
| 2522 |
mstore(0xa0, m5) |
||
| 2523 |
} |
||
| 2524 |
} |
||
| 2525 | |||
| 2526 |
function log(bytes32 p0, bool p1, uint256 p2) internal pure {
|
||
| 2527 |
bytes32 m0; |
||
| 2528 |
bytes32 m1; |
||
| 2529 |
bytes32 m2; |
||
| 2530 |
bytes32 m3; |
||
| 2531 |
bytes32 m4; |
||
| 2532 |
bytes32 m5; |
||
| 2533 |
/// @solidity memory-safe-assembly |
||
| 2534 |
assembly {
|
||
| 2535 |
function writeString(pos, w) {
|
||
| 2536 |
let length := 0 |
||
| 2537 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2538 |
mstore(pos, length) |
||
| 2539 |
let shift := sub(256, shl(3, length)) |
||
| 2540 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2541 |
} |
||
| 2542 |
m0 := mload(0x00) |
||
| 2543 |
m1 := mload(0x20) |
||
| 2544 |
m2 := mload(0x40) |
||
| 2545 |
m3 := mload(0x60) |
||
| 2546 |
m4 := mload(0x80) |
||
| 2547 |
m5 := mload(0xa0) |
||
| 2548 |
// Selector of `log(string,bool,uint256)`. |
||
| 2549 |
mstore(0x00, 0xc95958d6) |
||
| 2550 |
mstore(0x20, 0x60) |
||
| 2551 |
mstore(0x40, p1) |
||
| 2552 |
mstore(0x60, p2) |
||
| 2553 |
writeString(0x80, p0) |
||
| 2554 |
} |
||
| 2555 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2556 |
/// @solidity memory-safe-assembly |
||
| 2557 |
assembly {
|
||
| 2558 |
mstore(0x00, m0) |
||
| 2559 |
mstore(0x20, m1) |
||
| 2560 |
mstore(0x40, m2) |
||
| 2561 |
mstore(0x60, m3) |
||
| 2562 |
mstore(0x80, m4) |
||
| 2563 |
mstore(0xa0, m5) |
||
| 2564 |
} |
||
| 2565 |
} |
||
| 2566 | |||
| 2567 |
function log(bytes32 p0, bool p1, bytes32 p2) internal pure {
|
||
| 2568 |
bytes32 m0; |
||
| 2569 |
bytes32 m1; |
||
| 2570 |
bytes32 m2; |
||
| 2571 |
bytes32 m3; |
||
| 2572 |
bytes32 m4; |
||
| 2573 |
bytes32 m5; |
||
| 2574 |
bytes32 m6; |
||
| 2575 |
bytes32 m7; |
||
| 2576 |
/// @solidity memory-safe-assembly |
||
| 2577 |
assembly {
|
||
| 2578 |
function writeString(pos, w) {
|
||
| 2579 |
let length := 0 |
||
| 2580 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2581 |
mstore(pos, length) |
||
| 2582 |
let shift := sub(256, shl(3, length)) |
||
| 2583 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2584 |
} |
||
| 2585 |
m0 := mload(0x00) |
||
| 2586 |
m1 := mload(0x20) |
||
| 2587 |
m2 := mload(0x40) |
||
| 2588 |
m3 := mload(0x60) |
||
| 2589 |
m4 := mload(0x80) |
||
| 2590 |
m5 := mload(0xa0) |
||
| 2591 |
m6 := mload(0xc0) |
||
| 2592 |
m7 := mload(0xe0) |
||
| 2593 |
// Selector of `log(string,bool,string)`. |
||
| 2594 |
mstore(0x00, 0xe298f47d) |
||
| 2595 |
mstore(0x20, 0x60) |
||
| 2596 |
mstore(0x40, p1) |
||
| 2597 |
mstore(0x60, 0xa0) |
||
| 2598 |
writeString(0x80, p0) |
||
| 2599 |
writeString(0xc0, p2) |
||
| 2600 |
} |
||
| 2601 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2602 |
/// @solidity memory-safe-assembly |
||
| 2603 |
assembly {
|
||
| 2604 |
mstore(0x00, m0) |
||
| 2605 |
mstore(0x20, m1) |
||
| 2606 |
mstore(0x40, m2) |
||
| 2607 |
mstore(0x60, m3) |
||
| 2608 |
mstore(0x80, m4) |
||
| 2609 |
mstore(0xa0, m5) |
||
| 2610 |
mstore(0xc0, m6) |
||
| 2611 |
mstore(0xe0, m7) |
||
| 2612 |
} |
||
| 2613 |
} |
||
| 2614 | |||
| 2615 |
function log(bytes32 p0, uint256 p1, address p2) internal pure {
|
||
| 2616 |
bytes32 m0; |
||
| 2617 |
bytes32 m1; |
||
| 2618 |
bytes32 m2; |
||
| 2619 |
bytes32 m3; |
||
| 2620 |
bytes32 m4; |
||
| 2621 |
bytes32 m5; |
||
| 2622 |
/// @solidity memory-safe-assembly |
||
| 2623 |
assembly {
|
||
| 2624 |
function writeString(pos, w) {
|
||
| 2625 |
let length := 0 |
||
| 2626 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2627 |
mstore(pos, length) |
||
| 2628 |
let shift := sub(256, shl(3, length)) |
||
| 2629 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2630 |
} |
||
| 2631 |
m0 := mload(0x00) |
||
| 2632 |
m1 := mload(0x20) |
||
| 2633 |
m2 := mload(0x40) |
||
| 2634 |
m3 := mload(0x60) |
||
| 2635 |
m4 := mload(0x80) |
||
| 2636 |
m5 := mload(0xa0) |
||
| 2637 |
// Selector of `log(string,uint256,address)`. |
||
| 2638 |
mstore(0x00, 0x1c7ec448) |
||
| 2639 |
mstore(0x20, 0x60) |
||
| 2640 |
mstore(0x40, p1) |
||
| 2641 |
mstore(0x60, p2) |
||
| 2642 |
writeString(0x80, p0) |
||
| 2643 |
} |
||
| 2644 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2645 |
/// @solidity memory-safe-assembly |
||
| 2646 |
assembly {
|
||
| 2647 |
mstore(0x00, m0) |
||
| 2648 |
mstore(0x20, m1) |
||
| 2649 |
mstore(0x40, m2) |
||
| 2650 |
mstore(0x60, m3) |
||
| 2651 |
mstore(0x80, m4) |
||
| 2652 |
mstore(0xa0, m5) |
||
| 2653 |
} |
||
| 2654 |
} |
||
| 2655 | |||
| 2656 |
function log(bytes32 p0, uint256 p1, bool p2) internal pure {
|
||
| 2657 |
bytes32 m0; |
||
| 2658 |
bytes32 m1; |
||
| 2659 |
bytes32 m2; |
||
| 2660 |
bytes32 m3; |
||
| 2661 |
bytes32 m4; |
||
| 2662 |
bytes32 m5; |
||
| 2663 |
/// @solidity memory-safe-assembly |
||
| 2664 |
assembly {
|
||
| 2665 |
function writeString(pos, w) {
|
||
| 2666 |
let length := 0 |
||
| 2667 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2668 |
mstore(pos, length) |
||
| 2669 |
let shift := sub(256, shl(3, length)) |
||
| 2670 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2671 |
} |
||
| 2672 |
m0 := mload(0x00) |
||
| 2673 |
m1 := mload(0x20) |
||
| 2674 |
m2 := mload(0x40) |
||
| 2675 |
m3 := mload(0x60) |
||
| 2676 |
m4 := mload(0x80) |
||
| 2677 |
m5 := mload(0xa0) |
||
| 2678 |
// Selector of `log(string,uint256,bool)`. |
||
| 2679 |
mstore(0x00, 0xca7733b1) |
||
| 2680 |
mstore(0x20, 0x60) |
||
| 2681 |
mstore(0x40, p1) |
||
| 2682 |
mstore(0x60, p2) |
||
| 2683 |
writeString(0x80, p0) |
||
| 2684 |
} |
||
| 2685 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2686 |
/// @solidity memory-safe-assembly |
||
| 2687 |
assembly {
|
||
| 2688 |
mstore(0x00, m0) |
||
| 2689 |
mstore(0x20, m1) |
||
| 2690 |
mstore(0x40, m2) |
||
| 2691 |
mstore(0x60, m3) |
||
| 2692 |
mstore(0x80, m4) |
||
| 2693 |
mstore(0xa0, m5) |
||
| 2694 |
} |
||
| 2695 |
} |
||
| 2696 | |||
| 2697 |
function log(bytes32 p0, uint256 p1, uint256 p2) internal pure {
|
||
| 2698 |
bytes32 m0; |
||
| 2699 |
bytes32 m1; |
||
| 2700 |
bytes32 m2; |
||
| 2701 |
bytes32 m3; |
||
| 2702 |
bytes32 m4; |
||
| 2703 |
bytes32 m5; |
||
| 2704 |
/// @solidity memory-safe-assembly |
||
| 2705 |
assembly {
|
||
| 2706 |
function writeString(pos, w) {
|
||
| 2707 |
let length := 0 |
||
| 2708 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2709 |
mstore(pos, length) |
||
| 2710 |
let shift := sub(256, shl(3, length)) |
||
| 2711 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2712 |
} |
||
| 2713 |
m0 := mload(0x00) |
||
| 2714 |
m1 := mload(0x20) |
||
| 2715 |
m2 := mload(0x40) |
||
| 2716 |
m3 := mload(0x60) |
||
| 2717 |
m4 := mload(0x80) |
||
| 2718 |
m5 := mload(0xa0) |
||
| 2719 |
// Selector of `log(string,uint256,uint256)`. |
||
| 2720 |
mstore(0x00, 0xca47c4eb) |
||
| 2721 |
mstore(0x20, 0x60) |
||
| 2722 |
mstore(0x40, p1) |
||
| 2723 |
mstore(0x60, p2) |
||
| 2724 |
writeString(0x80, p0) |
||
| 2725 |
} |
||
| 2726 |
_sendLogPayload(0x1c, 0xa4); |
||
| 2727 |
/// @solidity memory-safe-assembly |
||
| 2728 |
assembly {
|
||
| 2729 |
mstore(0x00, m0) |
||
| 2730 |
mstore(0x20, m1) |
||
| 2731 |
mstore(0x40, m2) |
||
| 2732 |
mstore(0x60, m3) |
||
| 2733 |
mstore(0x80, m4) |
||
| 2734 |
mstore(0xa0, m5) |
||
| 2735 |
} |
||
| 2736 |
} |
||
| 2737 | |||
| 2738 |
function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure {
|
||
| 2739 |
bytes32 m0; |
||
| 2740 |
bytes32 m1; |
||
| 2741 |
bytes32 m2; |
||
| 2742 |
bytes32 m3; |
||
| 2743 |
bytes32 m4; |
||
| 2744 |
bytes32 m5; |
||
| 2745 |
bytes32 m6; |
||
| 2746 |
bytes32 m7; |
||
| 2747 |
/// @solidity memory-safe-assembly |
||
| 2748 |
assembly {
|
||
| 2749 |
function writeString(pos, w) {
|
||
| 2750 |
let length := 0 |
||
| 2751 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2752 |
mstore(pos, length) |
||
| 2753 |
let shift := sub(256, shl(3, length)) |
||
| 2754 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2755 |
} |
||
| 2756 |
m0 := mload(0x00) |
||
| 2757 |
m1 := mload(0x20) |
||
| 2758 |
m2 := mload(0x40) |
||
| 2759 |
m3 := mload(0x60) |
||
| 2760 |
m4 := mload(0x80) |
||
| 2761 |
m5 := mload(0xa0) |
||
| 2762 |
m6 := mload(0xc0) |
||
| 2763 |
m7 := mload(0xe0) |
||
| 2764 |
// Selector of `log(string,uint256,string)`. |
||
| 2765 |
mstore(0x00, 0x5970e089) |
||
| 2766 |
mstore(0x20, 0x60) |
||
| 2767 |
mstore(0x40, p1) |
||
| 2768 |
mstore(0x60, 0xa0) |
||
| 2769 |
writeString(0x80, p0) |
||
| 2770 |
writeString(0xc0, p2) |
||
| 2771 |
} |
||
| 2772 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2773 |
/// @solidity memory-safe-assembly |
||
| 2774 |
assembly {
|
||
| 2775 |
mstore(0x00, m0) |
||
| 2776 |
mstore(0x20, m1) |
||
| 2777 |
mstore(0x40, m2) |
||
| 2778 |
mstore(0x60, m3) |
||
| 2779 |
mstore(0x80, m4) |
||
| 2780 |
mstore(0xa0, m5) |
||
| 2781 |
mstore(0xc0, m6) |
||
| 2782 |
mstore(0xe0, m7) |
||
| 2783 |
} |
||
| 2784 |
} |
||
| 2785 | |||
| 2786 |
function log(bytes32 p0, bytes32 p1, address p2) internal pure {
|
||
| 2787 |
bytes32 m0; |
||
| 2788 |
bytes32 m1; |
||
| 2789 |
bytes32 m2; |
||
| 2790 |
bytes32 m3; |
||
| 2791 |
bytes32 m4; |
||
| 2792 |
bytes32 m5; |
||
| 2793 |
bytes32 m6; |
||
| 2794 |
bytes32 m7; |
||
| 2795 |
/// @solidity memory-safe-assembly |
||
| 2796 |
assembly {
|
||
| 2797 |
function writeString(pos, w) {
|
||
| 2798 |
let length := 0 |
||
| 2799 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2800 |
mstore(pos, length) |
||
| 2801 |
let shift := sub(256, shl(3, length)) |
||
| 2802 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2803 |
} |
||
| 2804 |
m0 := mload(0x00) |
||
| 2805 |
m1 := mload(0x20) |
||
| 2806 |
m2 := mload(0x40) |
||
| 2807 |
m3 := mload(0x60) |
||
| 2808 |
m4 := mload(0x80) |
||
| 2809 |
m5 := mload(0xa0) |
||
| 2810 |
m6 := mload(0xc0) |
||
| 2811 |
m7 := mload(0xe0) |
||
| 2812 |
// Selector of `log(string,string,address)`. |
||
| 2813 |
mstore(0x00, 0x95ed0195) |
||
| 2814 |
mstore(0x20, 0x60) |
||
| 2815 |
mstore(0x40, 0xa0) |
||
| 2816 |
mstore(0x60, p2) |
||
| 2817 |
writeString(0x80, p0) |
||
| 2818 |
writeString(0xc0, p1) |
||
| 2819 |
} |
||
| 2820 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2821 |
/// @solidity memory-safe-assembly |
||
| 2822 |
assembly {
|
||
| 2823 |
mstore(0x00, m0) |
||
| 2824 |
mstore(0x20, m1) |
||
| 2825 |
mstore(0x40, m2) |
||
| 2826 |
mstore(0x60, m3) |
||
| 2827 |
mstore(0x80, m4) |
||
| 2828 |
mstore(0xa0, m5) |
||
| 2829 |
mstore(0xc0, m6) |
||
| 2830 |
mstore(0xe0, m7) |
||
| 2831 |
} |
||
| 2832 |
} |
||
| 2833 | |||
| 2834 |
function log(bytes32 p0, bytes32 p1, bool p2) internal pure {
|
||
| 2835 |
bytes32 m0; |
||
| 2836 |
bytes32 m1; |
||
| 2837 |
bytes32 m2; |
||
| 2838 |
bytes32 m3; |
||
| 2839 |
bytes32 m4; |
||
| 2840 |
bytes32 m5; |
||
| 2841 |
bytes32 m6; |
||
| 2842 |
bytes32 m7; |
||
| 2843 |
/// @solidity memory-safe-assembly |
||
| 2844 |
assembly {
|
||
| 2845 |
function writeString(pos, w) {
|
||
| 2846 |
let length := 0 |
||
| 2847 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2848 |
mstore(pos, length) |
||
| 2849 |
let shift := sub(256, shl(3, length)) |
||
| 2850 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2851 |
} |
||
| 2852 |
m0 := mload(0x00) |
||
| 2853 |
m1 := mload(0x20) |
||
| 2854 |
m2 := mload(0x40) |
||
| 2855 |
m3 := mload(0x60) |
||
| 2856 |
m4 := mload(0x80) |
||
| 2857 |
m5 := mload(0xa0) |
||
| 2858 |
m6 := mload(0xc0) |
||
| 2859 |
m7 := mload(0xe0) |
||
| 2860 |
// Selector of `log(string,string,bool)`. |
||
| 2861 |
mstore(0x00, 0xb0e0f9b5) |
||
| 2862 |
mstore(0x20, 0x60) |
||
| 2863 |
mstore(0x40, 0xa0) |
||
| 2864 |
mstore(0x60, p2) |
||
| 2865 |
writeString(0x80, p0) |
||
| 2866 |
writeString(0xc0, p1) |
||
| 2867 |
} |
||
| 2868 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2869 |
/// @solidity memory-safe-assembly |
||
| 2870 |
assembly {
|
||
| 2871 |
mstore(0x00, m0) |
||
| 2872 |
mstore(0x20, m1) |
||
| 2873 |
mstore(0x40, m2) |
||
| 2874 |
mstore(0x60, m3) |
||
| 2875 |
mstore(0x80, m4) |
||
| 2876 |
mstore(0xa0, m5) |
||
| 2877 |
mstore(0xc0, m6) |
||
| 2878 |
mstore(0xe0, m7) |
||
| 2879 |
} |
||
| 2880 |
} |
||
| 2881 | |||
| 2882 |
function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure {
|
||
| 2883 |
bytes32 m0; |
||
| 2884 |
bytes32 m1; |
||
| 2885 |
bytes32 m2; |
||
| 2886 |
bytes32 m3; |
||
| 2887 |
bytes32 m4; |
||
| 2888 |
bytes32 m5; |
||
| 2889 |
bytes32 m6; |
||
| 2890 |
bytes32 m7; |
||
| 2891 |
/// @solidity memory-safe-assembly |
||
| 2892 |
assembly {
|
||
| 2893 |
function writeString(pos, w) {
|
||
| 2894 |
let length := 0 |
||
| 2895 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2896 |
mstore(pos, length) |
||
| 2897 |
let shift := sub(256, shl(3, length)) |
||
| 2898 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2899 |
} |
||
| 2900 |
m0 := mload(0x00) |
||
| 2901 |
m1 := mload(0x20) |
||
| 2902 |
m2 := mload(0x40) |
||
| 2903 |
m3 := mload(0x60) |
||
| 2904 |
m4 := mload(0x80) |
||
| 2905 |
m5 := mload(0xa0) |
||
| 2906 |
m6 := mload(0xc0) |
||
| 2907 |
m7 := mload(0xe0) |
||
| 2908 |
// Selector of `log(string,string,uint256)`. |
||
| 2909 |
mstore(0x00, 0x5821efa1) |
||
| 2910 |
mstore(0x20, 0x60) |
||
| 2911 |
mstore(0x40, 0xa0) |
||
| 2912 |
mstore(0x60, p2) |
||
| 2913 |
writeString(0x80, p0) |
||
| 2914 |
writeString(0xc0, p1) |
||
| 2915 |
} |
||
| 2916 |
_sendLogPayload(0x1c, 0xe4); |
||
| 2917 |
/// @solidity memory-safe-assembly |
||
| 2918 |
assembly {
|
||
| 2919 |
mstore(0x00, m0) |
||
| 2920 |
mstore(0x20, m1) |
||
| 2921 |
mstore(0x40, m2) |
||
| 2922 |
mstore(0x60, m3) |
||
| 2923 |
mstore(0x80, m4) |
||
| 2924 |
mstore(0xa0, m5) |
||
| 2925 |
mstore(0xc0, m6) |
||
| 2926 |
mstore(0xe0, m7) |
||
| 2927 |
} |
||
| 2928 |
} |
||
| 2929 | |||
| 2930 |
function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure {
|
||
| 2931 |
bytes32 m0; |
||
| 2932 |
bytes32 m1; |
||
| 2933 |
bytes32 m2; |
||
| 2934 |
bytes32 m3; |
||
| 2935 |
bytes32 m4; |
||
| 2936 |
bytes32 m5; |
||
| 2937 |
bytes32 m6; |
||
| 2938 |
bytes32 m7; |
||
| 2939 |
bytes32 m8; |
||
| 2940 |
bytes32 m9; |
||
| 2941 |
/// @solidity memory-safe-assembly |
||
| 2942 |
assembly {
|
||
| 2943 |
function writeString(pos, w) {
|
||
| 2944 |
let length := 0 |
||
| 2945 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 2946 |
mstore(pos, length) |
||
| 2947 |
let shift := sub(256, shl(3, length)) |
||
| 2948 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 2949 |
} |
||
| 2950 |
m0 := mload(0x00) |
||
| 2951 |
m1 := mload(0x20) |
||
| 2952 |
m2 := mload(0x40) |
||
| 2953 |
m3 := mload(0x60) |
||
| 2954 |
m4 := mload(0x80) |
||
| 2955 |
m5 := mload(0xa0) |
||
| 2956 |
m6 := mload(0xc0) |
||
| 2957 |
m7 := mload(0xe0) |
||
| 2958 |
m8 := mload(0x100) |
||
| 2959 |
m9 := mload(0x120) |
||
| 2960 |
// Selector of `log(string,string,string)`. |
||
| 2961 |
mstore(0x00, 0x2ced7cef) |
||
| 2962 |
mstore(0x20, 0x60) |
||
| 2963 |
mstore(0x40, 0xa0) |
||
| 2964 |
mstore(0x60, 0xe0) |
||
| 2965 |
writeString(0x80, p0) |
||
| 2966 |
writeString(0xc0, p1) |
||
| 2967 |
writeString(0x100, p2) |
||
| 2968 |
} |
||
| 2969 |
_sendLogPayload(0x1c, 0x124); |
||
| 2970 |
/// @solidity memory-safe-assembly |
||
| 2971 |
assembly {
|
||
| 2972 |
mstore(0x00, m0) |
||
| 2973 |
mstore(0x20, m1) |
||
| 2974 |
mstore(0x40, m2) |
||
| 2975 |
mstore(0x60, m3) |
||
| 2976 |
mstore(0x80, m4) |
||
| 2977 |
mstore(0xa0, m5) |
||
| 2978 |
mstore(0xc0, m6) |
||
| 2979 |
mstore(0xe0, m7) |
||
| 2980 |
mstore(0x100, m8) |
||
| 2981 |
mstore(0x120, m9) |
||
| 2982 |
} |
||
| 2983 |
} |
||
| 2984 | |||
| 2985 |
function log(address p0, address p1, address p2, address p3) internal pure {
|
||
| 2986 |
bytes32 m0; |
||
| 2987 |
bytes32 m1; |
||
| 2988 |
bytes32 m2; |
||
| 2989 |
bytes32 m3; |
||
| 2990 |
bytes32 m4; |
||
| 2991 |
/// @solidity memory-safe-assembly |
||
| 2992 |
assembly {
|
||
| 2993 |
m0 := mload(0x00) |
||
| 2994 |
m1 := mload(0x20) |
||
| 2995 |
m2 := mload(0x40) |
||
| 2996 |
m3 := mload(0x60) |
||
| 2997 |
m4 := mload(0x80) |
||
| 2998 |
// Selector of `log(address,address,address,address)`. |
||
| 2999 |
mstore(0x00, 0x665bf134) |
||
| 3000 |
mstore(0x20, p0) |
||
| 3001 |
mstore(0x40, p1) |
||
| 3002 |
mstore(0x60, p2) |
||
| 3003 |
mstore(0x80, p3) |
||
| 3004 |
} |
||
| 3005 |
_sendLogPayload(0x1c, 0x84); |
||
| 3006 |
/// @solidity memory-safe-assembly |
||
| 3007 |
assembly {
|
||
| 3008 |
mstore(0x00, m0) |
||
| 3009 |
mstore(0x20, m1) |
||
| 3010 |
mstore(0x40, m2) |
||
| 3011 |
mstore(0x60, m3) |
||
| 3012 |
mstore(0x80, m4) |
||
| 3013 |
} |
||
| 3014 |
} |
||
| 3015 | |||
| 3016 |
function log(address p0, address p1, address p2, bool p3) internal pure {
|
||
| 3017 |
bytes32 m0; |
||
| 3018 |
bytes32 m1; |
||
| 3019 |
bytes32 m2; |
||
| 3020 |
bytes32 m3; |
||
| 3021 |
bytes32 m4; |
||
| 3022 |
/// @solidity memory-safe-assembly |
||
| 3023 |
assembly {
|
||
| 3024 |
m0 := mload(0x00) |
||
| 3025 |
m1 := mload(0x20) |
||
| 3026 |
m2 := mload(0x40) |
||
| 3027 |
m3 := mload(0x60) |
||
| 3028 |
m4 := mload(0x80) |
||
| 3029 |
// Selector of `log(address,address,address,bool)`. |
||
| 3030 |
mstore(0x00, 0x0e378994) |
||
| 3031 |
mstore(0x20, p0) |
||
| 3032 |
mstore(0x40, p1) |
||
| 3033 |
mstore(0x60, p2) |
||
| 3034 |
mstore(0x80, p3) |
||
| 3035 |
} |
||
| 3036 |
_sendLogPayload(0x1c, 0x84); |
||
| 3037 |
/// @solidity memory-safe-assembly |
||
| 3038 |
assembly {
|
||
| 3039 |
mstore(0x00, m0) |
||
| 3040 |
mstore(0x20, m1) |
||
| 3041 |
mstore(0x40, m2) |
||
| 3042 |
mstore(0x60, m3) |
||
| 3043 |
mstore(0x80, m4) |
||
| 3044 |
} |
||
| 3045 |
} |
||
| 3046 | |||
| 3047 |
function log(address p0, address p1, address p2, uint256 p3) internal pure {
|
||
| 3048 |
bytes32 m0; |
||
| 3049 |
bytes32 m1; |
||
| 3050 |
bytes32 m2; |
||
| 3051 |
bytes32 m3; |
||
| 3052 |
bytes32 m4; |
||
| 3053 |
/// @solidity memory-safe-assembly |
||
| 3054 |
assembly {
|
||
| 3055 |
m0 := mload(0x00) |
||
| 3056 |
m1 := mload(0x20) |
||
| 3057 |
m2 := mload(0x40) |
||
| 3058 |
m3 := mload(0x60) |
||
| 3059 |
m4 := mload(0x80) |
||
| 3060 |
// Selector of `log(address,address,address,uint256)`. |
||
| 3061 |
mstore(0x00, 0x94250d77) |
||
| 3062 |
mstore(0x20, p0) |
||
| 3063 |
mstore(0x40, p1) |
||
| 3064 |
mstore(0x60, p2) |
||
| 3065 |
mstore(0x80, p3) |
||
| 3066 |
} |
||
| 3067 |
_sendLogPayload(0x1c, 0x84); |
||
| 3068 |
/// @solidity memory-safe-assembly |
||
| 3069 |
assembly {
|
||
| 3070 |
mstore(0x00, m0) |
||
| 3071 |
mstore(0x20, m1) |
||
| 3072 |
mstore(0x40, m2) |
||
| 3073 |
mstore(0x60, m3) |
||
| 3074 |
mstore(0x80, m4) |
||
| 3075 |
} |
||
| 3076 |
} |
||
| 3077 | |||
| 3078 |
function log(address p0, address p1, address p2, bytes32 p3) internal pure {
|
||
| 3079 |
bytes32 m0; |
||
| 3080 |
bytes32 m1; |
||
| 3081 |
bytes32 m2; |
||
| 3082 |
bytes32 m3; |
||
| 3083 |
bytes32 m4; |
||
| 3084 |
bytes32 m5; |
||
| 3085 |
bytes32 m6; |
||
| 3086 |
/// @solidity memory-safe-assembly |
||
| 3087 |
assembly {
|
||
| 3088 |
function writeString(pos, w) {
|
||
| 3089 |
let length := 0 |
||
| 3090 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3091 |
mstore(pos, length) |
||
| 3092 |
let shift := sub(256, shl(3, length)) |
||
| 3093 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3094 |
} |
||
| 3095 |
m0 := mload(0x00) |
||
| 3096 |
m1 := mload(0x20) |
||
| 3097 |
m2 := mload(0x40) |
||
| 3098 |
m3 := mload(0x60) |
||
| 3099 |
m4 := mload(0x80) |
||
| 3100 |
m5 := mload(0xa0) |
||
| 3101 |
m6 := mload(0xc0) |
||
| 3102 |
// Selector of `log(address,address,address,string)`. |
||
| 3103 |
mstore(0x00, 0xf808da20) |
||
| 3104 |
mstore(0x20, p0) |
||
| 3105 |
mstore(0x40, p1) |
||
| 3106 |
mstore(0x60, p2) |
||
| 3107 |
mstore(0x80, 0x80) |
||
| 3108 |
writeString(0xa0, p3) |
||
| 3109 |
} |
||
| 3110 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3111 |
/// @solidity memory-safe-assembly |
||
| 3112 |
assembly {
|
||
| 3113 |
mstore(0x00, m0) |
||
| 3114 |
mstore(0x20, m1) |
||
| 3115 |
mstore(0x40, m2) |
||
| 3116 |
mstore(0x60, m3) |
||
| 3117 |
mstore(0x80, m4) |
||
| 3118 |
mstore(0xa0, m5) |
||
| 3119 |
mstore(0xc0, m6) |
||
| 3120 |
} |
||
| 3121 |
} |
||
| 3122 | |||
| 3123 |
function log(address p0, address p1, bool p2, address p3) internal pure {
|
||
| 3124 |
bytes32 m0; |
||
| 3125 |
bytes32 m1; |
||
| 3126 |
bytes32 m2; |
||
| 3127 |
bytes32 m3; |
||
| 3128 |
bytes32 m4; |
||
| 3129 |
/// @solidity memory-safe-assembly |
||
| 3130 |
assembly {
|
||
| 3131 |
m0 := mload(0x00) |
||
| 3132 |
m1 := mload(0x20) |
||
| 3133 |
m2 := mload(0x40) |
||
| 3134 |
m3 := mload(0x60) |
||
| 3135 |
m4 := mload(0x80) |
||
| 3136 |
// Selector of `log(address,address,bool,address)`. |
||
| 3137 |
mstore(0x00, 0x9f1bc36e) |
||
| 3138 |
mstore(0x20, p0) |
||
| 3139 |
mstore(0x40, p1) |
||
| 3140 |
mstore(0x60, p2) |
||
| 3141 |
mstore(0x80, p3) |
||
| 3142 |
} |
||
| 3143 |
_sendLogPayload(0x1c, 0x84); |
||
| 3144 |
/// @solidity memory-safe-assembly |
||
| 3145 |
assembly {
|
||
| 3146 |
mstore(0x00, m0) |
||
| 3147 |
mstore(0x20, m1) |
||
| 3148 |
mstore(0x40, m2) |
||
| 3149 |
mstore(0x60, m3) |
||
| 3150 |
mstore(0x80, m4) |
||
| 3151 |
} |
||
| 3152 |
} |
||
| 3153 | |||
| 3154 |
function log(address p0, address p1, bool p2, bool p3) internal pure {
|
||
| 3155 |
bytes32 m0; |
||
| 3156 |
bytes32 m1; |
||
| 3157 |
bytes32 m2; |
||
| 3158 |
bytes32 m3; |
||
| 3159 |
bytes32 m4; |
||
| 3160 |
/// @solidity memory-safe-assembly |
||
| 3161 |
assembly {
|
||
| 3162 |
m0 := mload(0x00) |
||
| 3163 |
m1 := mload(0x20) |
||
| 3164 |
m2 := mload(0x40) |
||
| 3165 |
m3 := mload(0x60) |
||
| 3166 |
m4 := mload(0x80) |
||
| 3167 |
// Selector of `log(address,address,bool,bool)`. |
||
| 3168 |
mstore(0x00, 0x2cd4134a) |
||
| 3169 |
mstore(0x20, p0) |
||
| 3170 |
mstore(0x40, p1) |
||
| 3171 |
mstore(0x60, p2) |
||
| 3172 |
mstore(0x80, p3) |
||
| 3173 |
} |
||
| 3174 |
_sendLogPayload(0x1c, 0x84); |
||
| 3175 |
/// @solidity memory-safe-assembly |
||
| 3176 |
assembly {
|
||
| 3177 |
mstore(0x00, m0) |
||
| 3178 |
mstore(0x20, m1) |
||
| 3179 |
mstore(0x40, m2) |
||
| 3180 |
mstore(0x60, m3) |
||
| 3181 |
mstore(0x80, m4) |
||
| 3182 |
} |
||
| 3183 |
} |
||
| 3184 | |||
| 3185 |
function log(address p0, address p1, bool p2, uint256 p3) internal pure {
|
||
| 3186 |
bytes32 m0; |
||
| 3187 |
bytes32 m1; |
||
| 3188 |
bytes32 m2; |
||
| 3189 |
bytes32 m3; |
||
| 3190 |
bytes32 m4; |
||
| 3191 |
/// @solidity memory-safe-assembly |
||
| 3192 |
assembly {
|
||
| 3193 |
m0 := mload(0x00) |
||
| 3194 |
m1 := mload(0x20) |
||
| 3195 |
m2 := mload(0x40) |
||
| 3196 |
m3 := mload(0x60) |
||
| 3197 |
m4 := mload(0x80) |
||
| 3198 |
// Selector of `log(address,address,bool,uint256)`. |
||
| 3199 |
mstore(0x00, 0x3971e78c) |
||
| 3200 |
mstore(0x20, p0) |
||
| 3201 |
mstore(0x40, p1) |
||
| 3202 |
mstore(0x60, p2) |
||
| 3203 |
mstore(0x80, p3) |
||
| 3204 |
} |
||
| 3205 |
_sendLogPayload(0x1c, 0x84); |
||
| 3206 |
/// @solidity memory-safe-assembly |
||
| 3207 |
assembly {
|
||
| 3208 |
mstore(0x00, m0) |
||
| 3209 |
mstore(0x20, m1) |
||
| 3210 |
mstore(0x40, m2) |
||
| 3211 |
mstore(0x60, m3) |
||
| 3212 |
mstore(0x80, m4) |
||
| 3213 |
} |
||
| 3214 |
} |
||
| 3215 | |||
| 3216 |
function log(address p0, address p1, bool p2, bytes32 p3) internal pure {
|
||
| 3217 |
bytes32 m0; |
||
| 3218 |
bytes32 m1; |
||
| 3219 |
bytes32 m2; |
||
| 3220 |
bytes32 m3; |
||
| 3221 |
bytes32 m4; |
||
| 3222 |
bytes32 m5; |
||
| 3223 |
bytes32 m6; |
||
| 3224 |
/// @solidity memory-safe-assembly |
||
| 3225 |
assembly {
|
||
| 3226 |
function writeString(pos, w) {
|
||
| 3227 |
let length := 0 |
||
| 3228 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3229 |
mstore(pos, length) |
||
| 3230 |
let shift := sub(256, shl(3, length)) |
||
| 3231 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3232 |
} |
||
| 3233 |
m0 := mload(0x00) |
||
| 3234 |
m1 := mload(0x20) |
||
| 3235 |
m2 := mload(0x40) |
||
| 3236 |
m3 := mload(0x60) |
||
| 3237 |
m4 := mload(0x80) |
||
| 3238 |
m5 := mload(0xa0) |
||
| 3239 |
m6 := mload(0xc0) |
||
| 3240 |
// Selector of `log(address,address,bool,string)`. |
||
| 3241 |
mstore(0x00, 0xaa6540c8) |
||
| 3242 |
mstore(0x20, p0) |
||
| 3243 |
mstore(0x40, p1) |
||
| 3244 |
mstore(0x60, p2) |
||
| 3245 |
mstore(0x80, 0x80) |
||
| 3246 |
writeString(0xa0, p3) |
||
| 3247 |
} |
||
| 3248 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3249 |
/// @solidity memory-safe-assembly |
||
| 3250 |
assembly {
|
||
| 3251 |
mstore(0x00, m0) |
||
| 3252 |
mstore(0x20, m1) |
||
| 3253 |
mstore(0x40, m2) |
||
| 3254 |
mstore(0x60, m3) |
||
| 3255 |
mstore(0x80, m4) |
||
| 3256 |
mstore(0xa0, m5) |
||
| 3257 |
mstore(0xc0, m6) |
||
| 3258 |
} |
||
| 3259 |
} |
||
| 3260 | |||
| 3261 |
function log(address p0, address p1, uint256 p2, address p3) internal pure {
|
||
| 3262 |
bytes32 m0; |
||
| 3263 |
bytes32 m1; |
||
| 3264 |
bytes32 m2; |
||
| 3265 |
bytes32 m3; |
||
| 3266 |
bytes32 m4; |
||
| 3267 |
/// @solidity memory-safe-assembly |
||
| 3268 |
assembly {
|
||
| 3269 |
m0 := mload(0x00) |
||
| 3270 |
m1 := mload(0x20) |
||
| 3271 |
m2 := mload(0x40) |
||
| 3272 |
m3 := mload(0x60) |
||
| 3273 |
m4 := mload(0x80) |
||
| 3274 |
// Selector of `log(address,address,uint256,address)`. |
||
| 3275 |
mstore(0x00, 0x8da6def5) |
||
| 3276 |
mstore(0x20, p0) |
||
| 3277 |
mstore(0x40, p1) |
||
| 3278 |
mstore(0x60, p2) |
||
| 3279 |
mstore(0x80, p3) |
||
| 3280 |
} |
||
| 3281 |
_sendLogPayload(0x1c, 0x84); |
||
| 3282 |
/// @solidity memory-safe-assembly |
||
| 3283 |
assembly {
|
||
| 3284 |
mstore(0x00, m0) |
||
| 3285 |
mstore(0x20, m1) |
||
| 3286 |
mstore(0x40, m2) |
||
| 3287 |
mstore(0x60, m3) |
||
| 3288 |
mstore(0x80, m4) |
||
| 3289 |
} |
||
| 3290 |
} |
||
| 3291 | |||
| 3292 |
function log(address p0, address p1, uint256 p2, bool p3) internal pure {
|
||
| 3293 |
bytes32 m0; |
||
| 3294 |
bytes32 m1; |
||
| 3295 |
bytes32 m2; |
||
| 3296 |
bytes32 m3; |
||
| 3297 |
bytes32 m4; |
||
| 3298 |
/// @solidity memory-safe-assembly |
||
| 3299 |
assembly {
|
||
| 3300 |
m0 := mload(0x00) |
||
| 3301 |
m1 := mload(0x20) |
||
| 3302 |
m2 := mload(0x40) |
||
| 3303 |
m3 := mload(0x60) |
||
| 3304 |
m4 := mload(0x80) |
||
| 3305 |
// Selector of `log(address,address,uint256,bool)`. |
||
| 3306 |
mstore(0x00, 0x9b4254e2) |
||
| 3307 |
mstore(0x20, p0) |
||
| 3308 |
mstore(0x40, p1) |
||
| 3309 |
mstore(0x60, p2) |
||
| 3310 |
mstore(0x80, p3) |
||
| 3311 |
} |
||
| 3312 |
_sendLogPayload(0x1c, 0x84); |
||
| 3313 |
/// @solidity memory-safe-assembly |
||
| 3314 |
assembly {
|
||
| 3315 |
mstore(0x00, m0) |
||
| 3316 |
mstore(0x20, m1) |
||
| 3317 |
mstore(0x40, m2) |
||
| 3318 |
mstore(0x60, m3) |
||
| 3319 |
mstore(0x80, m4) |
||
| 3320 |
} |
||
| 3321 |
} |
||
| 3322 | |||
| 3323 |
function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
|
||
| 3324 |
bytes32 m0; |
||
| 3325 |
bytes32 m1; |
||
| 3326 |
bytes32 m2; |
||
| 3327 |
bytes32 m3; |
||
| 3328 |
bytes32 m4; |
||
| 3329 |
/// @solidity memory-safe-assembly |
||
| 3330 |
assembly {
|
||
| 3331 |
m0 := mload(0x00) |
||
| 3332 |
m1 := mload(0x20) |
||
| 3333 |
m2 := mload(0x40) |
||
| 3334 |
m3 := mload(0x60) |
||
| 3335 |
m4 := mload(0x80) |
||
| 3336 |
// Selector of `log(address,address,uint256,uint256)`. |
||
| 3337 |
mstore(0x00, 0xbe553481) |
||
| 3338 |
mstore(0x20, p0) |
||
| 3339 |
mstore(0x40, p1) |
||
| 3340 |
mstore(0x60, p2) |
||
| 3341 |
mstore(0x80, p3) |
||
| 3342 |
} |
||
| 3343 |
_sendLogPayload(0x1c, 0x84); |
||
| 3344 |
/// @solidity memory-safe-assembly |
||
| 3345 |
assembly {
|
||
| 3346 |
mstore(0x00, m0) |
||
| 3347 |
mstore(0x20, m1) |
||
| 3348 |
mstore(0x40, m2) |
||
| 3349 |
mstore(0x60, m3) |
||
| 3350 |
mstore(0x80, m4) |
||
| 3351 |
} |
||
| 3352 |
} |
||
| 3353 | |||
| 3354 |
function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 3355 |
bytes32 m0; |
||
| 3356 |
bytes32 m1; |
||
| 3357 |
bytes32 m2; |
||
| 3358 |
bytes32 m3; |
||
| 3359 |
bytes32 m4; |
||
| 3360 |
bytes32 m5; |
||
| 3361 |
bytes32 m6; |
||
| 3362 |
/// @solidity memory-safe-assembly |
||
| 3363 |
assembly {
|
||
| 3364 |
function writeString(pos, w) {
|
||
| 3365 |
let length := 0 |
||
| 3366 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3367 |
mstore(pos, length) |
||
| 3368 |
let shift := sub(256, shl(3, length)) |
||
| 3369 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3370 |
} |
||
| 3371 |
m0 := mload(0x00) |
||
| 3372 |
m1 := mload(0x20) |
||
| 3373 |
m2 := mload(0x40) |
||
| 3374 |
m3 := mload(0x60) |
||
| 3375 |
m4 := mload(0x80) |
||
| 3376 |
m5 := mload(0xa0) |
||
| 3377 |
m6 := mload(0xc0) |
||
| 3378 |
// Selector of `log(address,address,uint256,string)`. |
||
| 3379 |
mstore(0x00, 0xfdb4f990) |
||
| 3380 |
mstore(0x20, p0) |
||
| 3381 |
mstore(0x40, p1) |
||
| 3382 |
mstore(0x60, p2) |
||
| 3383 |
mstore(0x80, 0x80) |
||
| 3384 |
writeString(0xa0, p3) |
||
| 3385 |
} |
||
| 3386 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3387 |
/// @solidity memory-safe-assembly |
||
| 3388 |
assembly {
|
||
| 3389 |
mstore(0x00, m0) |
||
| 3390 |
mstore(0x20, m1) |
||
| 3391 |
mstore(0x40, m2) |
||
| 3392 |
mstore(0x60, m3) |
||
| 3393 |
mstore(0x80, m4) |
||
| 3394 |
mstore(0xa0, m5) |
||
| 3395 |
mstore(0xc0, m6) |
||
| 3396 |
} |
||
| 3397 |
} |
||
| 3398 | |||
| 3399 |
function log(address p0, address p1, bytes32 p2, address p3) internal pure {
|
||
| 3400 |
bytes32 m0; |
||
| 3401 |
bytes32 m1; |
||
| 3402 |
bytes32 m2; |
||
| 3403 |
bytes32 m3; |
||
| 3404 |
bytes32 m4; |
||
| 3405 |
bytes32 m5; |
||
| 3406 |
bytes32 m6; |
||
| 3407 |
/// @solidity memory-safe-assembly |
||
| 3408 |
assembly {
|
||
| 3409 |
function writeString(pos, w) {
|
||
| 3410 |
let length := 0 |
||
| 3411 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3412 |
mstore(pos, length) |
||
| 3413 |
let shift := sub(256, shl(3, length)) |
||
| 3414 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3415 |
} |
||
| 3416 |
m0 := mload(0x00) |
||
| 3417 |
m1 := mload(0x20) |
||
| 3418 |
m2 := mload(0x40) |
||
| 3419 |
m3 := mload(0x60) |
||
| 3420 |
m4 := mload(0x80) |
||
| 3421 |
m5 := mload(0xa0) |
||
| 3422 |
m6 := mload(0xc0) |
||
| 3423 |
// Selector of `log(address,address,string,address)`. |
||
| 3424 |
mstore(0x00, 0x8f736d16) |
||
| 3425 |
mstore(0x20, p0) |
||
| 3426 |
mstore(0x40, p1) |
||
| 3427 |
mstore(0x60, 0x80) |
||
| 3428 |
mstore(0x80, p3) |
||
| 3429 |
writeString(0xa0, p2) |
||
| 3430 |
} |
||
| 3431 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3432 |
/// @solidity memory-safe-assembly |
||
| 3433 |
assembly {
|
||
| 3434 |
mstore(0x00, m0) |
||
| 3435 |
mstore(0x20, m1) |
||
| 3436 |
mstore(0x40, m2) |
||
| 3437 |
mstore(0x60, m3) |
||
| 3438 |
mstore(0x80, m4) |
||
| 3439 |
mstore(0xa0, m5) |
||
| 3440 |
mstore(0xc0, m6) |
||
| 3441 |
} |
||
| 3442 |
} |
||
| 3443 | |||
| 3444 |
function log(address p0, address p1, bytes32 p2, bool p3) internal pure {
|
||
| 3445 |
bytes32 m0; |
||
| 3446 |
bytes32 m1; |
||
| 3447 |
bytes32 m2; |
||
| 3448 |
bytes32 m3; |
||
| 3449 |
bytes32 m4; |
||
| 3450 |
bytes32 m5; |
||
| 3451 |
bytes32 m6; |
||
| 3452 |
/// @solidity memory-safe-assembly |
||
| 3453 |
assembly {
|
||
| 3454 |
function writeString(pos, w) {
|
||
| 3455 |
let length := 0 |
||
| 3456 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3457 |
mstore(pos, length) |
||
| 3458 |
let shift := sub(256, shl(3, length)) |
||
| 3459 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3460 |
} |
||
| 3461 |
m0 := mload(0x00) |
||
| 3462 |
m1 := mload(0x20) |
||
| 3463 |
m2 := mload(0x40) |
||
| 3464 |
m3 := mload(0x60) |
||
| 3465 |
m4 := mload(0x80) |
||
| 3466 |
m5 := mload(0xa0) |
||
| 3467 |
m6 := mload(0xc0) |
||
| 3468 |
// Selector of `log(address,address,string,bool)`. |
||
| 3469 |
mstore(0x00, 0x6f1a594e) |
||
| 3470 |
mstore(0x20, p0) |
||
| 3471 |
mstore(0x40, p1) |
||
| 3472 |
mstore(0x60, 0x80) |
||
| 3473 |
mstore(0x80, p3) |
||
| 3474 |
writeString(0xa0, p2) |
||
| 3475 |
} |
||
| 3476 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3477 |
/// @solidity memory-safe-assembly |
||
| 3478 |
assembly {
|
||
| 3479 |
mstore(0x00, m0) |
||
| 3480 |
mstore(0x20, m1) |
||
| 3481 |
mstore(0x40, m2) |
||
| 3482 |
mstore(0x60, m3) |
||
| 3483 |
mstore(0x80, m4) |
||
| 3484 |
mstore(0xa0, m5) |
||
| 3485 |
mstore(0xc0, m6) |
||
| 3486 |
} |
||
| 3487 |
} |
||
| 3488 | |||
| 3489 |
function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 3490 |
bytes32 m0; |
||
| 3491 |
bytes32 m1; |
||
| 3492 |
bytes32 m2; |
||
| 3493 |
bytes32 m3; |
||
| 3494 |
bytes32 m4; |
||
| 3495 |
bytes32 m5; |
||
| 3496 |
bytes32 m6; |
||
| 3497 |
/// @solidity memory-safe-assembly |
||
| 3498 |
assembly {
|
||
| 3499 |
function writeString(pos, w) {
|
||
| 3500 |
let length := 0 |
||
| 3501 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3502 |
mstore(pos, length) |
||
| 3503 |
let shift := sub(256, shl(3, length)) |
||
| 3504 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3505 |
} |
||
| 3506 |
m0 := mload(0x00) |
||
| 3507 |
m1 := mload(0x20) |
||
| 3508 |
m2 := mload(0x40) |
||
| 3509 |
m3 := mload(0x60) |
||
| 3510 |
m4 := mload(0x80) |
||
| 3511 |
m5 := mload(0xa0) |
||
| 3512 |
m6 := mload(0xc0) |
||
| 3513 |
// Selector of `log(address,address,string,uint256)`. |
||
| 3514 |
mstore(0x00, 0xef1cefe7) |
||
| 3515 |
mstore(0x20, p0) |
||
| 3516 |
mstore(0x40, p1) |
||
| 3517 |
mstore(0x60, 0x80) |
||
| 3518 |
mstore(0x80, p3) |
||
| 3519 |
writeString(0xa0, p2) |
||
| 3520 |
} |
||
| 3521 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3522 |
/// @solidity memory-safe-assembly |
||
| 3523 |
assembly {
|
||
| 3524 |
mstore(0x00, m0) |
||
| 3525 |
mstore(0x20, m1) |
||
| 3526 |
mstore(0x40, m2) |
||
| 3527 |
mstore(0x60, m3) |
||
| 3528 |
mstore(0x80, m4) |
||
| 3529 |
mstore(0xa0, m5) |
||
| 3530 |
mstore(0xc0, m6) |
||
| 3531 |
} |
||
| 3532 |
} |
||
| 3533 | |||
| 3534 |
function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 3535 |
bytes32 m0; |
||
| 3536 |
bytes32 m1; |
||
| 3537 |
bytes32 m2; |
||
| 3538 |
bytes32 m3; |
||
| 3539 |
bytes32 m4; |
||
| 3540 |
bytes32 m5; |
||
| 3541 |
bytes32 m6; |
||
| 3542 |
bytes32 m7; |
||
| 3543 |
bytes32 m8; |
||
| 3544 |
/// @solidity memory-safe-assembly |
||
| 3545 |
assembly {
|
||
| 3546 |
function writeString(pos, w) {
|
||
| 3547 |
let length := 0 |
||
| 3548 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3549 |
mstore(pos, length) |
||
| 3550 |
let shift := sub(256, shl(3, length)) |
||
| 3551 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3552 |
} |
||
| 3553 |
m0 := mload(0x00) |
||
| 3554 |
m1 := mload(0x20) |
||
| 3555 |
m2 := mload(0x40) |
||
| 3556 |
m3 := mload(0x60) |
||
| 3557 |
m4 := mload(0x80) |
||
| 3558 |
m5 := mload(0xa0) |
||
| 3559 |
m6 := mload(0xc0) |
||
| 3560 |
m7 := mload(0xe0) |
||
| 3561 |
m8 := mload(0x100) |
||
| 3562 |
// Selector of `log(address,address,string,string)`. |
||
| 3563 |
mstore(0x00, 0x21bdaf25) |
||
| 3564 |
mstore(0x20, p0) |
||
| 3565 |
mstore(0x40, p1) |
||
| 3566 |
mstore(0x60, 0x80) |
||
| 3567 |
mstore(0x80, 0xc0) |
||
| 3568 |
writeString(0xa0, p2) |
||
| 3569 |
writeString(0xe0, p3) |
||
| 3570 |
} |
||
| 3571 |
_sendLogPayload(0x1c, 0x104); |
||
| 3572 |
/// @solidity memory-safe-assembly |
||
| 3573 |
assembly {
|
||
| 3574 |
mstore(0x00, m0) |
||
| 3575 |
mstore(0x20, m1) |
||
| 3576 |
mstore(0x40, m2) |
||
| 3577 |
mstore(0x60, m3) |
||
| 3578 |
mstore(0x80, m4) |
||
| 3579 |
mstore(0xa0, m5) |
||
| 3580 |
mstore(0xc0, m6) |
||
| 3581 |
mstore(0xe0, m7) |
||
| 3582 |
mstore(0x100, m8) |
||
| 3583 |
} |
||
| 3584 |
} |
||
| 3585 | |||
| 3586 |
function log(address p0, bool p1, address p2, address p3) internal pure {
|
||
| 3587 |
bytes32 m0; |
||
| 3588 |
bytes32 m1; |
||
| 3589 |
bytes32 m2; |
||
| 3590 |
bytes32 m3; |
||
| 3591 |
bytes32 m4; |
||
| 3592 |
/// @solidity memory-safe-assembly |
||
| 3593 |
assembly {
|
||
| 3594 |
m0 := mload(0x00) |
||
| 3595 |
m1 := mload(0x20) |
||
| 3596 |
m2 := mload(0x40) |
||
| 3597 |
m3 := mload(0x60) |
||
| 3598 |
m4 := mload(0x80) |
||
| 3599 |
// Selector of `log(address,bool,address,address)`. |
||
| 3600 |
mstore(0x00, 0x660375dd) |
||
| 3601 |
mstore(0x20, p0) |
||
| 3602 |
mstore(0x40, p1) |
||
| 3603 |
mstore(0x60, p2) |
||
| 3604 |
mstore(0x80, p3) |
||
| 3605 |
} |
||
| 3606 |
_sendLogPayload(0x1c, 0x84); |
||
| 3607 |
/// @solidity memory-safe-assembly |
||
| 3608 |
assembly {
|
||
| 3609 |
mstore(0x00, m0) |
||
| 3610 |
mstore(0x20, m1) |
||
| 3611 |
mstore(0x40, m2) |
||
| 3612 |
mstore(0x60, m3) |
||
| 3613 |
mstore(0x80, m4) |
||
| 3614 |
} |
||
| 3615 |
} |
||
| 3616 | |||
| 3617 |
function log(address p0, bool p1, address p2, bool p3) internal pure {
|
||
| 3618 |
bytes32 m0; |
||
| 3619 |
bytes32 m1; |
||
| 3620 |
bytes32 m2; |
||
| 3621 |
bytes32 m3; |
||
| 3622 |
bytes32 m4; |
||
| 3623 |
/// @solidity memory-safe-assembly |
||
| 3624 |
assembly {
|
||
| 3625 |
m0 := mload(0x00) |
||
| 3626 |
m1 := mload(0x20) |
||
| 3627 |
m2 := mload(0x40) |
||
| 3628 |
m3 := mload(0x60) |
||
| 3629 |
m4 := mload(0x80) |
||
| 3630 |
// Selector of `log(address,bool,address,bool)`. |
||
| 3631 |
mstore(0x00, 0xa6f50b0f) |
||
| 3632 |
mstore(0x20, p0) |
||
| 3633 |
mstore(0x40, p1) |
||
| 3634 |
mstore(0x60, p2) |
||
| 3635 |
mstore(0x80, p3) |
||
| 3636 |
} |
||
| 3637 |
_sendLogPayload(0x1c, 0x84); |
||
| 3638 |
/// @solidity memory-safe-assembly |
||
| 3639 |
assembly {
|
||
| 3640 |
mstore(0x00, m0) |
||
| 3641 |
mstore(0x20, m1) |
||
| 3642 |
mstore(0x40, m2) |
||
| 3643 |
mstore(0x60, m3) |
||
| 3644 |
mstore(0x80, m4) |
||
| 3645 |
} |
||
| 3646 |
} |
||
| 3647 | |||
| 3648 |
function log(address p0, bool p1, address p2, uint256 p3) internal pure {
|
||
| 3649 |
bytes32 m0; |
||
| 3650 |
bytes32 m1; |
||
| 3651 |
bytes32 m2; |
||
| 3652 |
bytes32 m3; |
||
| 3653 |
bytes32 m4; |
||
| 3654 |
/// @solidity memory-safe-assembly |
||
| 3655 |
assembly {
|
||
| 3656 |
m0 := mload(0x00) |
||
| 3657 |
m1 := mload(0x20) |
||
| 3658 |
m2 := mload(0x40) |
||
| 3659 |
m3 := mload(0x60) |
||
| 3660 |
m4 := mload(0x80) |
||
| 3661 |
// Selector of `log(address,bool,address,uint256)`. |
||
| 3662 |
mstore(0x00, 0xa75c59de) |
||
| 3663 |
mstore(0x20, p0) |
||
| 3664 |
mstore(0x40, p1) |
||
| 3665 |
mstore(0x60, p2) |
||
| 3666 |
mstore(0x80, p3) |
||
| 3667 |
} |
||
| 3668 |
_sendLogPayload(0x1c, 0x84); |
||
| 3669 |
/// @solidity memory-safe-assembly |
||
| 3670 |
assembly {
|
||
| 3671 |
mstore(0x00, m0) |
||
| 3672 |
mstore(0x20, m1) |
||
| 3673 |
mstore(0x40, m2) |
||
| 3674 |
mstore(0x60, m3) |
||
| 3675 |
mstore(0x80, m4) |
||
| 3676 |
} |
||
| 3677 |
} |
||
| 3678 | |||
| 3679 |
function log(address p0, bool p1, address p2, bytes32 p3) internal pure {
|
||
| 3680 |
bytes32 m0; |
||
| 3681 |
bytes32 m1; |
||
| 3682 |
bytes32 m2; |
||
| 3683 |
bytes32 m3; |
||
| 3684 |
bytes32 m4; |
||
| 3685 |
bytes32 m5; |
||
| 3686 |
bytes32 m6; |
||
| 3687 |
/// @solidity memory-safe-assembly |
||
| 3688 |
assembly {
|
||
| 3689 |
function writeString(pos, w) {
|
||
| 3690 |
let length := 0 |
||
| 3691 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3692 |
mstore(pos, length) |
||
| 3693 |
let shift := sub(256, shl(3, length)) |
||
| 3694 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3695 |
} |
||
| 3696 |
m0 := mload(0x00) |
||
| 3697 |
m1 := mload(0x20) |
||
| 3698 |
m2 := mload(0x40) |
||
| 3699 |
m3 := mload(0x60) |
||
| 3700 |
m4 := mload(0x80) |
||
| 3701 |
m5 := mload(0xa0) |
||
| 3702 |
m6 := mload(0xc0) |
||
| 3703 |
// Selector of `log(address,bool,address,string)`. |
||
| 3704 |
mstore(0x00, 0x2dd778e6) |
||
| 3705 |
mstore(0x20, p0) |
||
| 3706 |
mstore(0x40, p1) |
||
| 3707 |
mstore(0x60, p2) |
||
| 3708 |
mstore(0x80, 0x80) |
||
| 3709 |
writeString(0xa0, p3) |
||
| 3710 |
} |
||
| 3711 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3712 |
/// @solidity memory-safe-assembly |
||
| 3713 |
assembly {
|
||
| 3714 |
mstore(0x00, m0) |
||
| 3715 |
mstore(0x20, m1) |
||
| 3716 |
mstore(0x40, m2) |
||
| 3717 |
mstore(0x60, m3) |
||
| 3718 |
mstore(0x80, m4) |
||
| 3719 |
mstore(0xa0, m5) |
||
| 3720 |
mstore(0xc0, m6) |
||
| 3721 |
} |
||
| 3722 |
} |
||
| 3723 | |||
| 3724 |
function log(address p0, bool p1, bool p2, address p3) internal pure {
|
||
| 3725 |
bytes32 m0; |
||
| 3726 |
bytes32 m1; |
||
| 3727 |
bytes32 m2; |
||
| 3728 |
bytes32 m3; |
||
| 3729 |
bytes32 m4; |
||
| 3730 |
/// @solidity memory-safe-assembly |
||
| 3731 |
assembly {
|
||
| 3732 |
m0 := mload(0x00) |
||
| 3733 |
m1 := mload(0x20) |
||
| 3734 |
m2 := mload(0x40) |
||
| 3735 |
m3 := mload(0x60) |
||
| 3736 |
m4 := mload(0x80) |
||
| 3737 |
// Selector of `log(address,bool,bool,address)`. |
||
| 3738 |
mstore(0x00, 0xcf394485) |
||
| 3739 |
mstore(0x20, p0) |
||
| 3740 |
mstore(0x40, p1) |
||
| 3741 |
mstore(0x60, p2) |
||
| 3742 |
mstore(0x80, p3) |
||
| 3743 |
} |
||
| 3744 |
_sendLogPayload(0x1c, 0x84); |
||
| 3745 |
/// @solidity memory-safe-assembly |
||
| 3746 |
assembly {
|
||
| 3747 |
mstore(0x00, m0) |
||
| 3748 |
mstore(0x20, m1) |
||
| 3749 |
mstore(0x40, m2) |
||
| 3750 |
mstore(0x60, m3) |
||
| 3751 |
mstore(0x80, m4) |
||
| 3752 |
} |
||
| 3753 |
} |
||
| 3754 | |||
| 3755 |
function log(address p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 3756 |
bytes32 m0; |
||
| 3757 |
bytes32 m1; |
||
| 3758 |
bytes32 m2; |
||
| 3759 |
bytes32 m3; |
||
| 3760 |
bytes32 m4; |
||
| 3761 |
/// @solidity memory-safe-assembly |
||
| 3762 |
assembly {
|
||
| 3763 |
m0 := mload(0x00) |
||
| 3764 |
m1 := mload(0x20) |
||
| 3765 |
m2 := mload(0x40) |
||
| 3766 |
m3 := mload(0x60) |
||
| 3767 |
m4 := mload(0x80) |
||
| 3768 |
// Selector of `log(address,bool,bool,bool)`. |
||
| 3769 |
mstore(0x00, 0xcac43479) |
||
| 3770 |
mstore(0x20, p0) |
||
| 3771 |
mstore(0x40, p1) |
||
| 3772 |
mstore(0x60, p2) |
||
| 3773 |
mstore(0x80, p3) |
||
| 3774 |
} |
||
| 3775 |
_sendLogPayload(0x1c, 0x84); |
||
| 3776 |
/// @solidity memory-safe-assembly |
||
| 3777 |
assembly {
|
||
| 3778 |
mstore(0x00, m0) |
||
| 3779 |
mstore(0x20, m1) |
||
| 3780 |
mstore(0x40, m2) |
||
| 3781 |
mstore(0x60, m3) |
||
| 3782 |
mstore(0x80, m4) |
||
| 3783 |
} |
||
| 3784 |
} |
||
| 3785 | |||
| 3786 |
function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
|
||
| 3787 |
bytes32 m0; |
||
| 3788 |
bytes32 m1; |
||
| 3789 |
bytes32 m2; |
||
| 3790 |
bytes32 m3; |
||
| 3791 |
bytes32 m4; |
||
| 3792 |
/// @solidity memory-safe-assembly |
||
| 3793 |
assembly {
|
||
| 3794 |
m0 := mload(0x00) |
||
| 3795 |
m1 := mload(0x20) |
||
| 3796 |
m2 := mload(0x40) |
||
| 3797 |
m3 := mload(0x60) |
||
| 3798 |
m4 := mload(0x80) |
||
| 3799 |
// Selector of `log(address,bool,bool,uint256)`. |
||
| 3800 |
mstore(0x00, 0x8c4e5de6) |
||
| 3801 |
mstore(0x20, p0) |
||
| 3802 |
mstore(0x40, p1) |
||
| 3803 |
mstore(0x60, p2) |
||
| 3804 |
mstore(0x80, p3) |
||
| 3805 |
} |
||
| 3806 |
_sendLogPayload(0x1c, 0x84); |
||
| 3807 |
/// @solidity memory-safe-assembly |
||
| 3808 |
assembly {
|
||
| 3809 |
mstore(0x00, m0) |
||
| 3810 |
mstore(0x20, m1) |
||
| 3811 |
mstore(0x40, m2) |
||
| 3812 |
mstore(0x60, m3) |
||
| 3813 |
mstore(0x80, m4) |
||
| 3814 |
} |
||
| 3815 |
} |
||
| 3816 | |||
| 3817 |
function log(address p0, bool p1, bool p2, bytes32 p3) internal pure {
|
||
| 3818 |
bytes32 m0; |
||
| 3819 |
bytes32 m1; |
||
| 3820 |
bytes32 m2; |
||
| 3821 |
bytes32 m3; |
||
| 3822 |
bytes32 m4; |
||
| 3823 |
bytes32 m5; |
||
| 3824 |
bytes32 m6; |
||
| 3825 |
/// @solidity memory-safe-assembly |
||
| 3826 |
assembly {
|
||
| 3827 |
function writeString(pos, w) {
|
||
| 3828 |
let length := 0 |
||
| 3829 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3830 |
mstore(pos, length) |
||
| 3831 |
let shift := sub(256, shl(3, length)) |
||
| 3832 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3833 |
} |
||
| 3834 |
m0 := mload(0x00) |
||
| 3835 |
m1 := mload(0x20) |
||
| 3836 |
m2 := mload(0x40) |
||
| 3837 |
m3 := mload(0x60) |
||
| 3838 |
m4 := mload(0x80) |
||
| 3839 |
m5 := mload(0xa0) |
||
| 3840 |
m6 := mload(0xc0) |
||
| 3841 |
// Selector of `log(address,bool,bool,string)`. |
||
| 3842 |
mstore(0x00, 0xdfc4a2e8) |
||
| 3843 |
mstore(0x20, p0) |
||
| 3844 |
mstore(0x40, p1) |
||
| 3845 |
mstore(0x60, p2) |
||
| 3846 |
mstore(0x80, 0x80) |
||
| 3847 |
writeString(0xa0, p3) |
||
| 3848 |
} |
||
| 3849 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3850 |
/// @solidity memory-safe-assembly |
||
| 3851 |
assembly {
|
||
| 3852 |
mstore(0x00, m0) |
||
| 3853 |
mstore(0x20, m1) |
||
| 3854 |
mstore(0x40, m2) |
||
| 3855 |
mstore(0x60, m3) |
||
| 3856 |
mstore(0x80, m4) |
||
| 3857 |
mstore(0xa0, m5) |
||
| 3858 |
mstore(0xc0, m6) |
||
| 3859 |
} |
||
| 3860 |
} |
||
| 3861 | |||
| 3862 |
function log(address p0, bool p1, uint256 p2, address p3) internal pure {
|
||
| 3863 |
bytes32 m0; |
||
| 3864 |
bytes32 m1; |
||
| 3865 |
bytes32 m2; |
||
| 3866 |
bytes32 m3; |
||
| 3867 |
bytes32 m4; |
||
| 3868 |
/// @solidity memory-safe-assembly |
||
| 3869 |
assembly {
|
||
| 3870 |
m0 := mload(0x00) |
||
| 3871 |
m1 := mload(0x20) |
||
| 3872 |
m2 := mload(0x40) |
||
| 3873 |
m3 := mload(0x60) |
||
| 3874 |
m4 := mload(0x80) |
||
| 3875 |
// Selector of `log(address,bool,uint256,address)`. |
||
| 3876 |
mstore(0x00, 0xccf790a1) |
||
| 3877 |
mstore(0x20, p0) |
||
| 3878 |
mstore(0x40, p1) |
||
| 3879 |
mstore(0x60, p2) |
||
| 3880 |
mstore(0x80, p3) |
||
| 3881 |
} |
||
| 3882 |
_sendLogPayload(0x1c, 0x84); |
||
| 3883 |
/// @solidity memory-safe-assembly |
||
| 3884 |
assembly {
|
||
| 3885 |
mstore(0x00, m0) |
||
| 3886 |
mstore(0x20, m1) |
||
| 3887 |
mstore(0x40, m2) |
||
| 3888 |
mstore(0x60, m3) |
||
| 3889 |
mstore(0x80, m4) |
||
| 3890 |
} |
||
| 3891 |
} |
||
| 3892 | |||
| 3893 |
function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
|
||
| 3894 |
bytes32 m0; |
||
| 3895 |
bytes32 m1; |
||
| 3896 |
bytes32 m2; |
||
| 3897 |
bytes32 m3; |
||
| 3898 |
bytes32 m4; |
||
| 3899 |
/// @solidity memory-safe-assembly |
||
| 3900 |
assembly {
|
||
| 3901 |
m0 := mload(0x00) |
||
| 3902 |
m1 := mload(0x20) |
||
| 3903 |
m2 := mload(0x40) |
||
| 3904 |
m3 := mload(0x60) |
||
| 3905 |
m4 := mload(0x80) |
||
| 3906 |
// Selector of `log(address,bool,uint256,bool)`. |
||
| 3907 |
mstore(0x00, 0xc4643e20) |
||
| 3908 |
mstore(0x20, p0) |
||
| 3909 |
mstore(0x40, p1) |
||
| 3910 |
mstore(0x60, p2) |
||
| 3911 |
mstore(0x80, p3) |
||
| 3912 |
} |
||
| 3913 |
_sendLogPayload(0x1c, 0x84); |
||
| 3914 |
/// @solidity memory-safe-assembly |
||
| 3915 |
assembly {
|
||
| 3916 |
mstore(0x00, m0) |
||
| 3917 |
mstore(0x20, m1) |
||
| 3918 |
mstore(0x40, m2) |
||
| 3919 |
mstore(0x60, m3) |
||
| 3920 |
mstore(0x80, m4) |
||
| 3921 |
} |
||
| 3922 |
} |
||
| 3923 | |||
| 3924 |
function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
|
||
| 3925 |
bytes32 m0; |
||
| 3926 |
bytes32 m1; |
||
| 3927 |
bytes32 m2; |
||
| 3928 |
bytes32 m3; |
||
| 3929 |
bytes32 m4; |
||
| 3930 |
/// @solidity memory-safe-assembly |
||
| 3931 |
assembly {
|
||
| 3932 |
m0 := mload(0x00) |
||
| 3933 |
m1 := mload(0x20) |
||
| 3934 |
m2 := mload(0x40) |
||
| 3935 |
m3 := mload(0x60) |
||
| 3936 |
m4 := mload(0x80) |
||
| 3937 |
// Selector of `log(address,bool,uint256,uint256)`. |
||
| 3938 |
mstore(0x00, 0x386ff5f4) |
||
| 3939 |
mstore(0x20, p0) |
||
| 3940 |
mstore(0x40, p1) |
||
| 3941 |
mstore(0x60, p2) |
||
| 3942 |
mstore(0x80, p3) |
||
| 3943 |
} |
||
| 3944 |
_sendLogPayload(0x1c, 0x84); |
||
| 3945 |
/// @solidity memory-safe-assembly |
||
| 3946 |
assembly {
|
||
| 3947 |
mstore(0x00, m0) |
||
| 3948 |
mstore(0x20, m1) |
||
| 3949 |
mstore(0x40, m2) |
||
| 3950 |
mstore(0x60, m3) |
||
| 3951 |
mstore(0x80, m4) |
||
| 3952 |
} |
||
| 3953 |
} |
||
| 3954 | |||
| 3955 |
function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 3956 |
bytes32 m0; |
||
| 3957 |
bytes32 m1; |
||
| 3958 |
bytes32 m2; |
||
| 3959 |
bytes32 m3; |
||
| 3960 |
bytes32 m4; |
||
| 3961 |
bytes32 m5; |
||
| 3962 |
bytes32 m6; |
||
| 3963 |
/// @solidity memory-safe-assembly |
||
| 3964 |
assembly {
|
||
| 3965 |
function writeString(pos, w) {
|
||
| 3966 |
let length := 0 |
||
| 3967 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 3968 |
mstore(pos, length) |
||
| 3969 |
let shift := sub(256, shl(3, length)) |
||
| 3970 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 3971 |
} |
||
| 3972 |
m0 := mload(0x00) |
||
| 3973 |
m1 := mload(0x20) |
||
| 3974 |
m2 := mload(0x40) |
||
| 3975 |
m3 := mload(0x60) |
||
| 3976 |
m4 := mload(0x80) |
||
| 3977 |
m5 := mload(0xa0) |
||
| 3978 |
m6 := mload(0xc0) |
||
| 3979 |
// Selector of `log(address,bool,uint256,string)`. |
||
| 3980 |
mstore(0x00, 0x0aa6cfad) |
||
| 3981 |
mstore(0x20, p0) |
||
| 3982 |
mstore(0x40, p1) |
||
| 3983 |
mstore(0x60, p2) |
||
| 3984 |
mstore(0x80, 0x80) |
||
| 3985 |
writeString(0xa0, p3) |
||
| 3986 |
} |
||
| 3987 |
_sendLogPayload(0x1c, 0xc4); |
||
| 3988 |
/// @solidity memory-safe-assembly |
||
| 3989 |
assembly {
|
||
| 3990 |
mstore(0x00, m0) |
||
| 3991 |
mstore(0x20, m1) |
||
| 3992 |
mstore(0x40, m2) |
||
| 3993 |
mstore(0x60, m3) |
||
| 3994 |
mstore(0x80, m4) |
||
| 3995 |
mstore(0xa0, m5) |
||
| 3996 |
mstore(0xc0, m6) |
||
| 3997 |
} |
||
| 3998 |
} |
||
| 3999 | |||
| 4000 |
function log(address p0, bool p1, bytes32 p2, address p3) internal pure {
|
||
| 4001 |
bytes32 m0; |
||
| 4002 |
bytes32 m1; |
||
| 4003 |
bytes32 m2; |
||
| 4004 |
bytes32 m3; |
||
| 4005 |
bytes32 m4; |
||
| 4006 |
bytes32 m5; |
||
| 4007 |
bytes32 m6; |
||
| 4008 |
/// @solidity memory-safe-assembly |
||
| 4009 |
assembly {
|
||
| 4010 |
function writeString(pos, w) {
|
||
| 4011 |
let length := 0 |
||
| 4012 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4013 |
mstore(pos, length) |
||
| 4014 |
let shift := sub(256, shl(3, length)) |
||
| 4015 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4016 |
} |
||
| 4017 |
m0 := mload(0x00) |
||
| 4018 |
m1 := mload(0x20) |
||
| 4019 |
m2 := mload(0x40) |
||
| 4020 |
m3 := mload(0x60) |
||
| 4021 |
m4 := mload(0x80) |
||
| 4022 |
m5 := mload(0xa0) |
||
| 4023 |
m6 := mload(0xc0) |
||
| 4024 |
// Selector of `log(address,bool,string,address)`. |
||
| 4025 |
mstore(0x00, 0x19fd4956) |
||
| 4026 |
mstore(0x20, p0) |
||
| 4027 |
mstore(0x40, p1) |
||
| 4028 |
mstore(0x60, 0x80) |
||
| 4029 |
mstore(0x80, p3) |
||
| 4030 |
writeString(0xa0, p2) |
||
| 4031 |
} |
||
| 4032 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4033 |
/// @solidity memory-safe-assembly |
||
| 4034 |
assembly {
|
||
| 4035 |
mstore(0x00, m0) |
||
| 4036 |
mstore(0x20, m1) |
||
| 4037 |
mstore(0x40, m2) |
||
| 4038 |
mstore(0x60, m3) |
||
| 4039 |
mstore(0x80, m4) |
||
| 4040 |
mstore(0xa0, m5) |
||
| 4041 |
mstore(0xc0, m6) |
||
| 4042 |
} |
||
| 4043 |
} |
||
| 4044 | |||
| 4045 |
function log(address p0, bool p1, bytes32 p2, bool p3) internal pure {
|
||
| 4046 |
bytes32 m0; |
||
| 4047 |
bytes32 m1; |
||
| 4048 |
bytes32 m2; |
||
| 4049 |
bytes32 m3; |
||
| 4050 |
bytes32 m4; |
||
| 4051 |
bytes32 m5; |
||
| 4052 |
bytes32 m6; |
||
| 4053 |
/// @solidity memory-safe-assembly |
||
| 4054 |
assembly {
|
||
| 4055 |
function writeString(pos, w) {
|
||
| 4056 |
let length := 0 |
||
| 4057 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4058 |
mstore(pos, length) |
||
| 4059 |
let shift := sub(256, shl(3, length)) |
||
| 4060 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4061 |
} |
||
| 4062 |
m0 := mload(0x00) |
||
| 4063 |
m1 := mload(0x20) |
||
| 4064 |
m2 := mload(0x40) |
||
| 4065 |
m3 := mload(0x60) |
||
| 4066 |
m4 := mload(0x80) |
||
| 4067 |
m5 := mload(0xa0) |
||
| 4068 |
m6 := mload(0xc0) |
||
| 4069 |
// Selector of `log(address,bool,string,bool)`. |
||
| 4070 |
mstore(0x00, 0x50ad461d) |
||
| 4071 |
mstore(0x20, p0) |
||
| 4072 |
mstore(0x40, p1) |
||
| 4073 |
mstore(0x60, 0x80) |
||
| 4074 |
mstore(0x80, p3) |
||
| 4075 |
writeString(0xa0, p2) |
||
| 4076 |
} |
||
| 4077 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4078 |
/// @solidity memory-safe-assembly |
||
| 4079 |
assembly {
|
||
| 4080 |
mstore(0x00, m0) |
||
| 4081 |
mstore(0x20, m1) |
||
| 4082 |
mstore(0x40, m2) |
||
| 4083 |
mstore(0x60, m3) |
||
| 4084 |
mstore(0x80, m4) |
||
| 4085 |
mstore(0xa0, m5) |
||
| 4086 |
mstore(0xc0, m6) |
||
| 4087 |
} |
||
| 4088 |
} |
||
| 4089 | |||
| 4090 |
function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 4091 |
bytes32 m0; |
||
| 4092 |
bytes32 m1; |
||
| 4093 |
bytes32 m2; |
||
| 4094 |
bytes32 m3; |
||
| 4095 |
bytes32 m4; |
||
| 4096 |
bytes32 m5; |
||
| 4097 |
bytes32 m6; |
||
| 4098 |
/// @solidity memory-safe-assembly |
||
| 4099 |
assembly {
|
||
| 4100 |
function writeString(pos, w) {
|
||
| 4101 |
let length := 0 |
||
| 4102 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4103 |
mstore(pos, length) |
||
| 4104 |
let shift := sub(256, shl(3, length)) |
||
| 4105 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4106 |
} |
||
| 4107 |
m0 := mload(0x00) |
||
| 4108 |
m1 := mload(0x20) |
||
| 4109 |
m2 := mload(0x40) |
||
| 4110 |
m3 := mload(0x60) |
||
| 4111 |
m4 := mload(0x80) |
||
| 4112 |
m5 := mload(0xa0) |
||
| 4113 |
m6 := mload(0xc0) |
||
| 4114 |
// Selector of `log(address,bool,string,uint256)`. |
||
| 4115 |
mstore(0x00, 0x80e6a20b) |
||
| 4116 |
mstore(0x20, p0) |
||
| 4117 |
mstore(0x40, p1) |
||
| 4118 |
mstore(0x60, 0x80) |
||
| 4119 |
mstore(0x80, p3) |
||
| 4120 |
writeString(0xa0, p2) |
||
| 4121 |
} |
||
| 4122 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4123 |
/// @solidity memory-safe-assembly |
||
| 4124 |
assembly {
|
||
| 4125 |
mstore(0x00, m0) |
||
| 4126 |
mstore(0x20, m1) |
||
| 4127 |
mstore(0x40, m2) |
||
| 4128 |
mstore(0x60, m3) |
||
| 4129 |
mstore(0x80, m4) |
||
| 4130 |
mstore(0xa0, m5) |
||
| 4131 |
mstore(0xc0, m6) |
||
| 4132 |
} |
||
| 4133 |
} |
||
| 4134 | |||
| 4135 |
function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 4136 |
bytes32 m0; |
||
| 4137 |
bytes32 m1; |
||
| 4138 |
bytes32 m2; |
||
| 4139 |
bytes32 m3; |
||
| 4140 |
bytes32 m4; |
||
| 4141 |
bytes32 m5; |
||
| 4142 |
bytes32 m6; |
||
| 4143 |
bytes32 m7; |
||
| 4144 |
bytes32 m8; |
||
| 4145 |
/// @solidity memory-safe-assembly |
||
| 4146 |
assembly {
|
||
| 4147 |
function writeString(pos, w) {
|
||
| 4148 |
let length := 0 |
||
| 4149 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4150 |
mstore(pos, length) |
||
| 4151 |
let shift := sub(256, shl(3, length)) |
||
| 4152 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4153 |
} |
||
| 4154 |
m0 := mload(0x00) |
||
| 4155 |
m1 := mload(0x20) |
||
| 4156 |
m2 := mload(0x40) |
||
| 4157 |
m3 := mload(0x60) |
||
| 4158 |
m4 := mload(0x80) |
||
| 4159 |
m5 := mload(0xa0) |
||
| 4160 |
m6 := mload(0xc0) |
||
| 4161 |
m7 := mload(0xe0) |
||
| 4162 |
m8 := mload(0x100) |
||
| 4163 |
// Selector of `log(address,bool,string,string)`. |
||
| 4164 |
mstore(0x00, 0x475c5c33) |
||
| 4165 |
mstore(0x20, p0) |
||
| 4166 |
mstore(0x40, p1) |
||
| 4167 |
mstore(0x60, 0x80) |
||
| 4168 |
mstore(0x80, 0xc0) |
||
| 4169 |
writeString(0xa0, p2) |
||
| 4170 |
writeString(0xe0, p3) |
||
| 4171 |
} |
||
| 4172 |
_sendLogPayload(0x1c, 0x104); |
||
| 4173 |
/// @solidity memory-safe-assembly |
||
| 4174 |
assembly {
|
||
| 4175 |
mstore(0x00, m0) |
||
| 4176 |
mstore(0x20, m1) |
||
| 4177 |
mstore(0x40, m2) |
||
| 4178 |
mstore(0x60, m3) |
||
| 4179 |
mstore(0x80, m4) |
||
| 4180 |
mstore(0xa0, m5) |
||
| 4181 |
mstore(0xc0, m6) |
||
| 4182 |
mstore(0xe0, m7) |
||
| 4183 |
mstore(0x100, m8) |
||
| 4184 |
} |
||
| 4185 |
} |
||
| 4186 | |||
| 4187 |
function log(address p0, uint256 p1, address p2, address p3) internal pure {
|
||
| 4188 |
bytes32 m0; |
||
| 4189 |
bytes32 m1; |
||
| 4190 |
bytes32 m2; |
||
| 4191 |
bytes32 m3; |
||
| 4192 |
bytes32 m4; |
||
| 4193 |
/// @solidity memory-safe-assembly |
||
| 4194 |
assembly {
|
||
| 4195 |
m0 := mload(0x00) |
||
| 4196 |
m1 := mload(0x20) |
||
| 4197 |
m2 := mload(0x40) |
||
| 4198 |
m3 := mload(0x60) |
||
| 4199 |
m4 := mload(0x80) |
||
| 4200 |
// Selector of `log(address,uint256,address,address)`. |
||
| 4201 |
mstore(0x00, 0x478d1c62) |
||
| 4202 |
mstore(0x20, p0) |
||
| 4203 |
mstore(0x40, p1) |
||
| 4204 |
mstore(0x60, p2) |
||
| 4205 |
mstore(0x80, p3) |
||
| 4206 |
} |
||
| 4207 |
_sendLogPayload(0x1c, 0x84); |
||
| 4208 |
/// @solidity memory-safe-assembly |
||
| 4209 |
assembly {
|
||
| 4210 |
mstore(0x00, m0) |
||
| 4211 |
mstore(0x20, m1) |
||
| 4212 |
mstore(0x40, m2) |
||
| 4213 |
mstore(0x60, m3) |
||
| 4214 |
mstore(0x80, m4) |
||
| 4215 |
} |
||
| 4216 |
} |
||
| 4217 | |||
| 4218 |
function log(address p0, uint256 p1, address p2, bool p3) internal pure {
|
||
| 4219 |
bytes32 m0; |
||
| 4220 |
bytes32 m1; |
||
| 4221 |
bytes32 m2; |
||
| 4222 |
bytes32 m3; |
||
| 4223 |
bytes32 m4; |
||
| 4224 |
/// @solidity memory-safe-assembly |
||
| 4225 |
assembly {
|
||
| 4226 |
m0 := mload(0x00) |
||
| 4227 |
m1 := mload(0x20) |
||
| 4228 |
m2 := mload(0x40) |
||
| 4229 |
m3 := mload(0x60) |
||
| 4230 |
m4 := mload(0x80) |
||
| 4231 |
// Selector of `log(address,uint256,address,bool)`. |
||
| 4232 |
mstore(0x00, 0xa1bcc9b3) |
||
| 4233 |
mstore(0x20, p0) |
||
| 4234 |
mstore(0x40, p1) |
||
| 4235 |
mstore(0x60, p2) |
||
| 4236 |
mstore(0x80, p3) |
||
| 4237 |
} |
||
| 4238 |
_sendLogPayload(0x1c, 0x84); |
||
| 4239 |
/// @solidity memory-safe-assembly |
||
| 4240 |
assembly {
|
||
| 4241 |
mstore(0x00, m0) |
||
| 4242 |
mstore(0x20, m1) |
||
| 4243 |
mstore(0x40, m2) |
||
| 4244 |
mstore(0x60, m3) |
||
| 4245 |
mstore(0x80, m4) |
||
| 4246 |
} |
||
| 4247 |
} |
||
| 4248 | |||
| 4249 |
function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
|
||
| 4250 |
bytes32 m0; |
||
| 4251 |
bytes32 m1; |
||
| 4252 |
bytes32 m2; |
||
| 4253 |
bytes32 m3; |
||
| 4254 |
bytes32 m4; |
||
| 4255 |
/// @solidity memory-safe-assembly |
||
| 4256 |
assembly {
|
||
| 4257 |
m0 := mload(0x00) |
||
| 4258 |
m1 := mload(0x20) |
||
| 4259 |
m2 := mload(0x40) |
||
| 4260 |
m3 := mload(0x60) |
||
| 4261 |
m4 := mload(0x80) |
||
| 4262 |
// Selector of `log(address,uint256,address,uint256)`. |
||
| 4263 |
mstore(0x00, 0x100f650e) |
||
| 4264 |
mstore(0x20, p0) |
||
| 4265 |
mstore(0x40, p1) |
||
| 4266 |
mstore(0x60, p2) |
||
| 4267 |
mstore(0x80, p3) |
||
| 4268 |
} |
||
| 4269 |
_sendLogPayload(0x1c, 0x84); |
||
| 4270 |
/// @solidity memory-safe-assembly |
||
| 4271 |
assembly {
|
||
| 4272 |
mstore(0x00, m0) |
||
| 4273 |
mstore(0x20, m1) |
||
| 4274 |
mstore(0x40, m2) |
||
| 4275 |
mstore(0x60, m3) |
||
| 4276 |
mstore(0x80, m4) |
||
| 4277 |
} |
||
| 4278 |
} |
||
| 4279 | |||
| 4280 |
function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure {
|
||
| 4281 |
bytes32 m0; |
||
| 4282 |
bytes32 m1; |
||
| 4283 |
bytes32 m2; |
||
| 4284 |
bytes32 m3; |
||
| 4285 |
bytes32 m4; |
||
| 4286 |
bytes32 m5; |
||
| 4287 |
bytes32 m6; |
||
| 4288 |
/// @solidity memory-safe-assembly |
||
| 4289 |
assembly {
|
||
| 4290 |
function writeString(pos, w) {
|
||
| 4291 |
let length := 0 |
||
| 4292 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4293 |
mstore(pos, length) |
||
| 4294 |
let shift := sub(256, shl(3, length)) |
||
| 4295 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4296 |
} |
||
| 4297 |
m0 := mload(0x00) |
||
| 4298 |
m1 := mload(0x20) |
||
| 4299 |
m2 := mload(0x40) |
||
| 4300 |
m3 := mload(0x60) |
||
| 4301 |
m4 := mload(0x80) |
||
| 4302 |
m5 := mload(0xa0) |
||
| 4303 |
m6 := mload(0xc0) |
||
| 4304 |
// Selector of `log(address,uint256,address,string)`. |
||
| 4305 |
mstore(0x00, 0x1da986ea) |
||
| 4306 |
mstore(0x20, p0) |
||
| 4307 |
mstore(0x40, p1) |
||
| 4308 |
mstore(0x60, p2) |
||
| 4309 |
mstore(0x80, 0x80) |
||
| 4310 |
writeString(0xa0, p3) |
||
| 4311 |
} |
||
| 4312 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4313 |
/// @solidity memory-safe-assembly |
||
| 4314 |
assembly {
|
||
| 4315 |
mstore(0x00, m0) |
||
| 4316 |
mstore(0x20, m1) |
||
| 4317 |
mstore(0x40, m2) |
||
| 4318 |
mstore(0x60, m3) |
||
| 4319 |
mstore(0x80, m4) |
||
| 4320 |
mstore(0xa0, m5) |
||
| 4321 |
mstore(0xc0, m6) |
||
| 4322 |
} |
||
| 4323 |
} |
||
| 4324 | |||
| 4325 |
function log(address p0, uint256 p1, bool p2, address p3) internal pure {
|
||
| 4326 |
bytes32 m0; |
||
| 4327 |
bytes32 m1; |
||
| 4328 |
bytes32 m2; |
||
| 4329 |
bytes32 m3; |
||
| 4330 |
bytes32 m4; |
||
| 4331 |
/// @solidity memory-safe-assembly |
||
| 4332 |
assembly {
|
||
| 4333 |
m0 := mload(0x00) |
||
| 4334 |
m1 := mload(0x20) |
||
| 4335 |
m2 := mload(0x40) |
||
| 4336 |
m3 := mload(0x60) |
||
| 4337 |
m4 := mload(0x80) |
||
| 4338 |
// Selector of `log(address,uint256,bool,address)`. |
||
| 4339 |
mstore(0x00, 0xa31bfdcc) |
||
| 4340 |
mstore(0x20, p0) |
||
| 4341 |
mstore(0x40, p1) |
||
| 4342 |
mstore(0x60, p2) |
||
| 4343 |
mstore(0x80, p3) |
||
| 4344 |
} |
||
| 4345 |
_sendLogPayload(0x1c, 0x84); |
||
| 4346 |
/// @solidity memory-safe-assembly |
||
| 4347 |
assembly {
|
||
| 4348 |
mstore(0x00, m0) |
||
| 4349 |
mstore(0x20, m1) |
||
| 4350 |
mstore(0x40, m2) |
||
| 4351 |
mstore(0x60, m3) |
||
| 4352 |
mstore(0x80, m4) |
||
| 4353 |
} |
||
| 4354 |
} |
||
| 4355 | |||
| 4356 |
function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
|
||
| 4357 |
bytes32 m0; |
||
| 4358 |
bytes32 m1; |
||
| 4359 |
bytes32 m2; |
||
| 4360 |
bytes32 m3; |
||
| 4361 |
bytes32 m4; |
||
| 4362 |
/// @solidity memory-safe-assembly |
||
| 4363 |
assembly {
|
||
| 4364 |
m0 := mload(0x00) |
||
| 4365 |
m1 := mload(0x20) |
||
| 4366 |
m2 := mload(0x40) |
||
| 4367 |
m3 := mload(0x60) |
||
| 4368 |
m4 := mload(0x80) |
||
| 4369 |
// Selector of `log(address,uint256,bool,bool)`. |
||
| 4370 |
mstore(0x00, 0x3bf5e537) |
||
| 4371 |
mstore(0x20, p0) |
||
| 4372 |
mstore(0x40, p1) |
||
| 4373 |
mstore(0x60, p2) |
||
| 4374 |
mstore(0x80, p3) |
||
| 4375 |
} |
||
| 4376 |
_sendLogPayload(0x1c, 0x84); |
||
| 4377 |
/// @solidity memory-safe-assembly |
||
| 4378 |
assembly {
|
||
| 4379 |
mstore(0x00, m0) |
||
| 4380 |
mstore(0x20, m1) |
||
| 4381 |
mstore(0x40, m2) |
||
| 4382 |
mstore(0x60, m3) |
||
| 4383 |
mstore(0x80, m4) |
||
| 4384 |
} |
||
| 4385 |
} |
||
| 4386 | |||
| 4387 |
function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
|
||
| 4388 |
bytes32 m0; |
||
| 4389 |
bytes32 m1; |
||
| 4390 |
bytes32 m2; |
||
| 4391 |
bytes32 m3; |
||
| 4392 |
bytes32 m4; |
||
| 4393 |
/// @solidity memory-safe-assembly |
||
| 4394 |
assembly {
|
||
| 4395 |
m0 := mload(0x00) |
||
| 4396 |
m1 := mload(0x20) |
||
| 4397 |
m2 := mload(0x40) |
||
| 4398 |
m3 := mload(0x60) |
||
| 4399 |
m4 := mload(0x80) |
||
| 4400 |
// Selector of `log(address,uint256,bool,uint256)`. |
||
| 4401 |
mstore(0x00, 0x22f6b999) |
||
| 4402 |
mstore(0x20, p0) |
||
| 4403 |
mstore(0x40, p1) |
||
| 4404 |
mstore(0x60, p2) |
||
| 4405 |
mstore(0x80, p3) |
||
| 4406 |
} |
||
| 4407 |
_sendLogPayload(0x1c, 0x84); |
||
| 4408 |
/// @solidity memory-safe-assembly |
||
| 4409 |
assembly {
|
||
| 4410 |
mstore(0x00, m0) |
||
| 4411 |
mstore(0x20, m1) |
||
| 4412 |
mstore(0x40, m2) |
||
| 4413 |
mstore(0x60, m3) |
||
| 4414 |
mstore(0x80, m4) |
||
| 4415 |
} |
||
| 4416 |
} |
||
| 4417 | |||
| 4418 |
function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure {
|
||
| 4419 |
bytes32 m0; |
||
| 4420 |
bytes32 m1; |
||
| 4421 |
bytes32 m2; |
||
| 4422 |
bytes32 m3; |
||
| 4423 |
bytes32 m4; |
||
| 4424 |
bytes32 m5; |
||
| 4425 |
bytes32 m6; |
||
| 4426 |
/// @solidity memory-safe-assembly |
||
| 4427 |
assembly {
|
||
| 4428 |
function writeString(pos, w) {
|
||
| 4429 |
let length := 0 |
||
| 4430 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4431 |
mstore(pos, length) |
||
| 4432 |
let shift := sub(256, shl(3, length)) |
||
| 4433 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4434 |
} |
||
| 4435 |
m0 := mload(0x00) |
||
| 4436 |
m1 := mload(0x20) |
||
| 4437 |
m2 := mload(0x40) |
||
| 4438 |
m3 := mload(0x60) |
||
| 4439 |
m4 := mload(0x80) |
||
| 4440 |
m5 := mload(0xa0) |
||
| 4441 |
m6 := mload(0xc0) |
||
| 4442 |
// Selector of `log(address,uint256,bool,string)`. |
||
| 4443 |
mstore(0x00, 0xc5ad85f9) |
||
| 4444 |
mstore(0x20, p0) |
||
| 4445 |
mstore(0x40, p1) |
||
| 4446 |
mstore(0x60, p2) |
||
| 4447 |
mstore(0x80, 0x80) |
||
| 4448 |
writeString(0xa0, p3) |
||
| 4449 |
} |
||
| 4450 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4451 |
/// @solidity memory-safe-assembly |
||
| 4452 |
assembly {
|
||
| 4453 |
mstore(0x00, m0) |
||
| 4454 |
mstore(0x20, m1) |
||
| 4455 |
mstore(0x40, m2) |
||
| 4456 |
mstore(0x60, m3) |
||
| 4457 |
mstore(0x80, m4) |
||
| 4458 |
mstore(0xa0, m5) |
||
| 4459 |
mstore(0xc0, m6) |
||
| 4460 |
} |
||
| 4461 |
} |
||
| 4462 | |||
| 4463 |
function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
|
||
| 4464 |
bytes32 m0; |
||
| 4465 |
bytes32 m1; |
||
| 4466 |
bytes32 m2; |
||
| 4467 |
bytes32 m3; |
||
| 4468 |
bytes32 m4; |
||
| 4469 |
/// @solidity memory-safe-assembly |
||
| 4470 |
assembly {
|
||
| 4471 |
m0 := mload(0x00) |
||
| 4472 |
m1 := mload(0x20) |
||
| 4473 |
m2 := mload(0x40) |
||
| 4474 |
m3 := mload(0x60) |
||
| 4475 |
m4 := mload(0x80) |
||
| 4476 |
// Selector of `log(address,uint256,uint256,address)`. |
||
| 4477 |
mstore(0x00, 0x20e3984d) |
||
| 4478 |
mstore(0x20, p0) |
||
| 4479 |
mstore(0x40, p1) |
||
| 4480 |
mstore(0x60, p2) |
||
| 4481 |
mstore(0x80, p3) |
||
| 4482 |
} |
||
| 4483 |
_sendLogPayload(0x1c, 0x84); |
||
| 4484 |
/// @solidity memory-safe-assembly |
||
| 4485 |
assembly {
|
||
| 4486 |
mstore(0x00, m0) |
||
| 4487 |
mstore(0x20, m1) |
||
| 4488 |
mstore(0x40, m2) |
||
| 4489 |
mstore(0x60, m3) |
||
| 4490 |
mstore(0x80, m4) |
||
| 4491 |
} |
||
| 4492 |
} |
||
| 4493 | |||
| 4494 |
function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
|
||
| 4495 |
bytes32 m0; |
||
| 4496 |
bytes32 m1; |
||
| 4497 |
bytes32 m2; |
||
| 4498 |
bytes32 m3; |
||
| 4499 |
bytes32 m4; |
||
| 4500 |
/// @solidity memory-safe-assembly |
||
| 4501 |
assembly {
|
||
| 4502 |
m0 := mload(0x00) |
||
| 4503 |
m1 := mload(0x20) |
||
| 4504 |
m2 := mload(0x40) |
||
| 4505 |
m3 := mload(0x60) |
||
| 4506 |
m4 := mload(0x80) |
||
| 4507 |
// Selector of `log(address,uint256,uint256,bool)`. |
||
| 4508 |
mstore(0x00, 0x66f1bc67) |
||
| 4509 |
mstore(0x20, p0) |
||
| 4510 |
mstore(0x40, p1) |
||
| 4511 |
mstore(0x60, p2) |
||
| 4512 |
mstore(0x80, p3) |
||
| 4513 |
} |
||
| 4514 |
_sendLogPayload(0x1c, 0x84); |
||
| 4515 |
/// @solidity memory-safe-assembly |
||
| 4516 |
assembly {
|
||
| 4517 |
mstore(0x00, m0) |
||
| 4518 |
mstore(0x20, m1) |
||
| 4519 |
mstore(0x40, m2) |
||
| 4520 |
mstore(0x60, m3) |
||
| 4521 |
mstore(0x80, m4) |
||
| 4522 |
} |
||
| 4523 |
} |
||
| 4524 | |||
| 4525 |
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 4526 |
bytes32 m0; |
||
| 4527 |
bytes32 m1; |
||
| 4528 |
bytes32 m2; |
||
| 4529 |
bytes32 m3; |
||
| 4530 |
bytes32 m4; |
||
| 4531 |
/// @solidity memory-safe-assembly |
||
| 4532 |
assembly {
|
||
| 4533 |
m0 := mload(0x00) |
||
| 4534 |
m1 := mload(0x20) |
||
| 4535 |
m2 := mload(0x40) |
||
| 4536 |
m3 := mload(0x60) |
||
| 4537 |
m4 := mload(0x80) |
||
| 4538 |
// Selector of `log(address,uint256,uint256,uint256)`. |
||
| 4539 |
mstore(0x00, 0x34f0e636) |
||
| 4540 |
mstore(0x20, p0) |
||
| 4541 |
mstore(0x40, p1) |
||
| 4542 |
mstore(0x60, p2) |
||
| 4543 |
mstore(0x80, p3) |
||
| 4544 |
} |
||
| 4545 |
_sendLogPayload(0x1c, 0x84); |
||
| 4546 |
/// @solidity memory-safe-assembly |
||
| 4547 |
assembly {
|
||
| 4548 |
mstore(0x00, m0) |
||
| 4549 |
mstore(0x20, m1) |
||
| 4550 |
mstore(0x40, m2) |
||
| 4551 |
mstore(0x60, m3) |
||
| 4552 |
mstore(0x80, m4) |
||
| 4553 |
} |
||
| 4554 |
} |
||
| 4555 | |||
| 4556 |
function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 4557 |
bytes32 m0; |
||
| 4558 |
bytes32 m1; |
||
| 4559 |
bytes32 m2; |
||
| 4560 |
bytes32 m3; |
||
| 4561 |
bytes32 m4; |
||
| 4562 |
bytes32 m5; |
||
| 4563 |
bytes32 m6; |
||
| 4564 |
/// @solidity memory-safe-assembly |
||
| 4565 |
assembly {
|
||
| 4566 |
function writeString(pos, w) {
|
||
| 4567 |
let length := 0 |
||
| 4568 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4569 |
mstore(pos, length) |
||
| 4570 |
let shift := sub(256, shl(3, length)) |
||
| 4571 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4572 |
} |
||
| 4573 |
m0 := mload(0x00) |
||
| 4574 |
m1 := mload(0x20) |
||
| 4575 |
m2 := mload(0x40) |
||
| 4576 |
m3 := mload(0x60) |
||
| 4577 |
m4 := mload(0x80) |
||
| 4578 |
m5 := mload(0xa0) |
||
| 4579 |
m6 := mload(0xc0) |
||
| 4580 |
// Selector of `log(address,uint256,uint256,string)`. |
||
| 4581 |
mstore(0x00, 0x4a28c017) |
||
| 4582 |
mstore(0x20, p0) |
||
| 4583 |
mstore(0x40, p1) |
||
| 4584 |
mstore(0x60, p2) |
||
| 4585 |
mstore(0x80, 0x80) |
||
| 4586 |
writeString(0xa0, p3) |
||
| 4587 |
} |
||
| 4588 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4589 |
/// @solidity memory-safe-assembly |
||
| 4590 |
assembly {
|
||
| 4591 |
mstore(0x00, m0) |
||
| 4592 |
mstore(0x20, m1) |
||
| 4593 |
mstore(0x40, m2) |
||
| 4594 |
mstore(0x60, m3) |
||
| 4595 |
mstore(0x80, m4) |
||
| 4596 |
mstore(0xa0, m5) |
||
| 4597 |
mstore(0xc0, m6) |
||
| 4598 |
} |
||
| 4599 |
} |
||
| 4600 | |||
| 4601 |
function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure {
|
||
| 4602 |
bytes32 m0; |
||
| 4603 |
bytes32 m1; |
||
| 4604 |
bytes32 m2; |
||
| 4605 |
bytes32 m3; |
||
| 4606 |
bytes32 m4; |
||
| 4607 |
bytes32 m5; |
||
| 4608 |
bytes32 m6; |
||
| 4609 |
/// @solidity memory-safe-assembly |
||
| 4610 |
assembly {
|
||
| 4611 |
function writeString(pos, w) {
|
||
| 4612 |
let length := 0 |
||
| 4613 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4614 |
mstore(pos, length) |
||
| 4615 |
let shift := sub(256, shl(3, length)) |
||
| 4616 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4617 |
} |
||
| 4618 |
m0 := mload(0x00) |
||
| 4619 |
m1 := mload(0x20) |
||
| 4620 |
m2 := mload(0x40) |
||
| 4621 |
m3 := mload(0x60) |
||
| 4622 |
m4 := mload(0x80) |
||
| 4623 |
m5 := mload(0xa0) |
||
| 4624 |
m6 := mload(0xc0) |
||
| 4625 |
// Selector of `log(address,uint256,string,address)`. |
||
| 4626 |
mstore(0x00, 0x5c430d47) |
||
| 4627 |
mstore(0x20, p0) |
||
| 4628 |
mstore(0x40, p1) |
||
| 4629 |
mstore(0x60, 0x80) |
||
| 4630 |
mstore(0x80, p3) |
||
| 4631 |
writeString(0xa0, p2) |
||
| 4632 |
} |
||
| 4633 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4634 |
/// @solidity memory-safe-assembly |
||
| 4635 |
assembly {
|
||
| 4636 |
mstore(0x00, m0) |
||
| 4637 |
mstore(0x20, m1) |
||
| 4638 |
mstore(0x40, m2) |
||
| 4639 |
mstore(0x60, m3) |
||
| 4640 |
mstore(0x80, m4) |
||
| 4641 |
mstore(0xa0, m5) |
||
| 4642 |
mstore(0xc0, m6) |
||
| 4643 |
} |
||
| 4644 |
} |
||
| 4645 | |||
| 4646 |
function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure {
|
||
| 4647 |
bytes32 m0; |
||
| 4648 |
bytes32 m1; |
||
| 4649 |
bytes32 m2; |
||
| 4650 |
bytes32 m3; |
||
| 4651 |
bytes32 m4; |
||
| 4652 |
bytes32 m5; |
||
| 4653 |
bytes32 m6; |
||
| 4654 |
/// @solidity memory-safe-assembly |
||
| 4655 |
assembly {
|
||
| 4656 |
function writeString(pos, w) {
|
||
| 4657 |
let length := 0 |
||
| 4658 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4659 |
mstore(pos, length) |
||
| 4660 |
let shift := sub(256, shl(3, length)) |
||
| 4661 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4662 |
} |
||
| 4663 |
m0 := mload(0x00) |
||
| 4664 |
m1 := mload(0x20) |
||
| 4665 |
m2 := mload(0x40) |
||
| 4666 |
m3 := mload(0x60) |
||
| 4667 |
m4 := mload(0x80) |
||
| 4668 |
m5 := mload(0xa0) |
||
| 4669 |
m6 := mload(0xc0) |
||
| 4670 |
// Selector of `log(address,uint256,string,bool)`. |
||
| 4671 |
mstore(0x00, 0xcf18105c) |
||
| 4672 |
mstore(0x20, p0) |
||
| 4673 |
mstore(0x40, p1) |
||
| 4674 |
mstore(0x60, 0x80) |
||
| 4675 |
mstore(0x80, p3) |
||
| 4676 |
writeString(0xa0, p2) |
||
| 4677 |
} |
||
| 4678 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4679 |
/// @solidity memory-safe-assembly |
||
| 4680 |
assembly {
|
||
| 4681 |
mstore(0x00, m0) |
||
| 4682 |
mstore(0x20, m1) |
||
| 4683 |
mstore(0x40, m2) |
||
| 4684 |
mstore(0x60, m3) |
||
| 4685 |
mstore(0x80, m4) |
||
| 4686 |
mstore(0xa0, m5) |
||
| 4687 |
mstore(0xc0, m6) |
||
| 4688 |
} |
||
| 4689 |
} |
||
| 4690 | |||
| 4691 |
function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 4692 |
bytes32 m0; |
||
| 4693 |
bytes32 m1; |
||
| 4694 |
bytes32 m2; |
||
| 4695 |
bytes32 m3; |
||
| 4696 |
bytes32 m4; |
||
| 4697 |
bytes32 m5; |
||
| 4698 |
bytes32 m6; |
||
| 4699 |
/// @solidity memory-safe-assembly |
||
| 4700 |
assembly {
|
||
| 4701 |
function writeString(pos, w) {
|
||
| 4702 |
let length := 0 |
||
| 4703 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4704 |
mstore(pos, length) |
||
| 4705 |
let shift := sub(256, shl(3, length)) |
||
| 4706 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4707 |
} |
||
| 4708 |
m0 := mload(0x00) |
||
| 4709 |
m1 := mload(0x20) |
||
| 4710 |
m2 := mload(0x40) |
||
| 4711 |
m3 := mload(0x60) |
||
| 4712 |
m4 := mload(0x80) |
||
| 4713 |
m5 := mload(0xa0) |
||
| 4714 |
m6 := mload(0xc0) |
||
| 4715 |
// Selector of `log(address,uint256,string,uint256)`. |
||
| 4716 |
mstore(0x00, 0xbf01f891) |
||
| 4717 |
mstore(0x20, p0) |
||
| 4718 |
mstore(0x40, p1) |
||
| 4719 |
mstore(0x60, 0x80) |
||
| 4720 |
mstore(0x80, p3) |
||
| 4721 |
writeString(0xa0, p2) |
||
| 4722 |
} |
||
| 4723 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4724 |
/// @solidity memory-safe-assembly |
||
| 4725 |
assembly {
|
||
| 4726 |
mstore(0x00, m0) |
||
| 4727 |
mstore(0x20, m1) |
||
| 4728 |
mstore(0x40, m2) |
||
| 4729 |
mstore(0x60, m3) |
||
| 4730 |
mstore(0x80, m4) |
||
| 4731 |
mstore(0xa0, m5) |
||
| 4732 |
mstore(0xc0, m6) |
||
| 4733 |
} |
||
| 4734 |
} |
||
| 4735 | |||
| 4736 |
function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 4737 |
bytes32 m0; |
||
| 4738 |
bytes32 m1; |
||
| 4739 |
bytes32 m2; |
||
| 4740 |
bytes32 m3; |
||
| 4741 |
bytes32 m4; |
||
| 4742 |
bytes32 m5; |
||
| 4743 |
bytes32 m6; |
||
| 4744 |
bytes32 m7; |
||
| 4745 |
bytes32 m8; |
||
| 4746 |
/// @solidity memory-safe-assembly |
||
| 4747 |
assembly {
|
||
| 4748 |
function writeString(pos, w) {
|
||
| 4749 |
let length := 0 |
||
| 4750 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4751 |
mstore(pos, length) |
||
| 4752 |
let shift := sub(256, shl(3, length)) |
||
| 4753 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4754 |
} |
||
| 4755 |
m0 := mload(0x00) |
||
| 4756 |
m1 := mload(0x20) |
||
| 4757 |
m2 := mload(0x40) |
||
| 4758 |
m3 := mload(0x60) |
||
| 4759 |
m4 := mload(0x80) |
||
| 4760 |
m5 := mload(0xa0) |
||
| 4761 |
m6 := mload(0xc0) |
||
| 4762 |
m7 := mload(0xe0) |
||
| 4763 |
m8 := mload(0x100) |
||
| 4764 |
// Selector of `log(address,uint256,string,string)`. |
||
| 4765 |
mstore(0x00, 0x88a8c406) |
||
| 4766 |
mstore(0x20, p0) |
||
| 4767 |
mstore(0x40, p1) |
||
| 4768 |
mstore(0x60, 0x80) |
||
| 4769 |
mstore(0x80, 0xc0) |
||
| 4770 |
writeString(0xa0, p2) |
||
| 4771 |
writeString(0xe0, p3) |
||
| 4772 |
} |
||
| 4773 |
_sendLogPayload(0x1c, 0x104); |
||
| 4774 |
/// @solidity memory-safe-assembly |
||
| 4775 |
assembly {
|
||
| 4776 |
mstore(0x00, m0) |
||
| 4777 |
mstore(0x20, m1) |
||
| 4778 |
mstore(0x40, m2) |
||
| 4779 |
mstore(0x60, m3) |
||
| 4780 |
mstore(0x80, m4) |
||
| 4781 |
mstore(0xa0, m5) |
||
| 4782 |
mstore(0xc0, m6) |
||
| 4783 |
mstore(0xe0, m7) |
||
| 4784 |
mstore(0x100, m8) |
||
| 4785 |
} |
||
| 4786 |
} |
||
| 4787 | |||
| 4788 |
function log(address p0, bytes32 p1, address p2, address p3) internal pure {
|
||
| 4789 |
bytes32 m0; |
||
| 4790 |
bytes32 m1; |
||
| 4791 |
bytes32 m2; |
||
| 4792 |
bytes32 m3; |
||
| 4793 |
bytes32 m4; |
||
| 4794 |
bytes32 m5; |
||
| 4795 |
bytes32 m6; |
||
| 4796 |
/// @solidity memory-safe-assembly |
||
| 4797 |
assembly {
|
||
| 4798 |
function writeString(pos, w) {
|
||
| 4799 |
let length := 0 |
||
| 4800 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4801 |
mstore(pos, length) |
||
| 4802 |
let shift := sub(256, shl(3, length)) |
||
| 4803 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4804 |
} |
||
| 4805 |
m0 := mload(0x00) |
||
| 4806 |
m1 := mload(0x20) |
||
| 4807 |
m2 := mload(0x40) |
||
| 4808 |
m3 := mload(0x60) |
||
| 4809 |
m4 := mload(0x80) |
||
| 4810 |
m5 := mload(0xa0) |
||
| 4811 |
m6 := mload(0xc0) |
||
| 4812 |
// Selector of `log(address,string,address,address)`. |
||
| 4813 |
mstore(0x00, 0x0d36fa20) |
||
| 4814 |
mstore(0x20, p0) |
||
| 4815 |
mstore(0x40, 0x80) |
||
| 4816 |
mstore(0x60, p2) |
||
| 4817 |
mstore(0x80, p3) |
||
| 4818 |
writeString(0xa0, p1) |
||
| 4819 |
} |
||
| 4820 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4821 |
/// @solidity memory-safe-assembly |
||
| 4822 |
assembly {
|
||
| 4823 |
mstore(0x00, m0) |
||
| 4824 |
mstore(0x20, m1) |
||
| 4825 |
mstore(0x40, m2) |
||
| 4826 |
mstore(0x60, m3) |
||
| 4827 |
mstore(0x80, m4) |
||
| 4828 |
mstore(0xa0, m5) |
||
| 4829 |
mstore(0xc0, m6) |
||
| 4830 |
} |
||
| 4831 |
} |
||
| 4832 | |||
| 4833 |
function log(address p0, bytes32 p1, address p2, bool p3) internal pure {
|
||
| 4834 |
bytes32 m0; |
||
| 4835 |
bytes32 m1; |
||
| 4836 |
bytes32 m2; |
||
| 4837 |
bytes32 m3; |
||
| 4838 |
bytes32 m4; |
||
| 4839 |
bytes32 m5; |
||
| 4840 |
bytes32 m6; |
||
| 4841 |
/// @solidity memory-safe-assembly |
||
| 4842 |
assembly {
|
||
| 4843 |
function writeString(pos, w) {
|
||
| 4844 |
let length := 0 |
||
| 4845 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4846 |
mstore(pos, length) |
||
| 4847 |
let shift := sub(256, shl(3, length)) |
||
| 4848 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4849 |
} |
||
| 4850 |
m0 := mload(0x00) |
||
| 4851 |
m1 := mload(0x20) |
||
| 4852 |
m2 := mload(0x40) |
||
| 4853 |
m3 := mload(0x60) |
||
| 4854 |
m4 := mload(0x80) |
||
| 4855 |
m5 := mload(0xa0) |
||
| 4856 |
m6 := mload(0xc0) |
||
| 4857 |
// Selector of `log(address,string,address,bool)`. |
||
| 4858 |
mstore(0x00, 0x0df12b76) |
||
| 4859 |
mstore(0x20, p0) |
||
| 4860 |
mstore(0x40, 0x80) |
||
| 4861 |
mstore(0x60, p2) |
||
| 4862 |
mstore(0x80, p3) |
||
| 4863 |
writeString(0xa0, p1) |
||
| 4864 |
} |
||
| 4865 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4866 |
/// @solidity memory-safe-assembly |
||
| 4867 |
assembly {
|
||
| 4868 |
mstore(0x00, m0) |
||
| 4869 |
mstore(0x20, m1) |
||
| 4870 |
mstore(0x40, m2) |
||
| 4871 |
mstore(0x60, m3) |
||
| 4872 |
mstore(0x80, m4) |
||
| 4873 |
mstore(0xa0, m5) |
||
| 4874 |
mstore(0xc0, m6) |
||
| 4875 |
} |
||
| 4876 |
} |
||
| 4877 | |||
| 4878 |
function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure {
|
||
| 4879 |
bytes32 m0; |
||
| 4880 |
bytes32 m1; |
||
| 4881 |
bytes32 m2; |
||
| 4882 |
bytes32 m3; |
||
| 4883 |
bytes32 m4; |
||
| 4884 |
bytes32 m5; |
||
| 4885 |
bytes32 m6; |
||
| 4886 |
/// @solidity memory-safe-assembly |
||
| 4887 |
assembly {
|
||
| 4888 |
function writeString(pos, w) {
|
||
| 4889 |
let length := 0 |
||
| 4890 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4891 |
mstore(pos, length) |
||
| 4892 |
let shift := sub(256, shl(3, length)) |
||
| 4893 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4894 |
} |
||
| 4895 |
m0 := mload(0x00) |
||
| 4896 |
m1 := mload(0x20) |
||
| 4897 |
m2 := mload(0x40) |
||
| 4898 |
m3 := mload(0x60) |
||
| 4899 |
m4 := mload(0x80) |
||
| 4900 |
m5 := mload(0xa0) |
||
| 4901 |
m6 := mload(0xc0) |
||
| 4902 |
// Selector of `log(address,string,address,uint256)`. |
||
| 4903 |
mstore(0x00, 0x457fe3cf) |
||
| 4904 |
mstore(0x20, p0) |
||
| 4905 |
mstore(0x40, 0x80) |
||
| 4906 |
mstore(0x60, p2) |
||
| 4907 |
mstore(0x80, p3) |
||
| 4908 |
writeString(0xa0, p1) |
||
| 4909 |
} |
||
| 4910 |
_sendLogPayload(0x1c, 0xc4); |
||
| 4911 |
/// @solidity memory-safe-assembly |
||
| 4912 |
assembly {
|
||
| 4913 |
mstore(0x00, m0) |
||
| 4914 |
mstore(0x20, m1) |
||
| 4915 |
mstore(0x40, m2) |
||
| 4916 |
mstore(0x60, m3) |
||
| 4917 |
mstore(0x80, m4) |
||
| 4918 |
mstore(0xa0, m5) |
||
| 4919 |
mstore(0xc0, m6) |
||
| 4920 |
} |
||
| 4921 |
} |
||
| 4922 | |||
| 4923 |
function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure {
|
||
| 4924 |
bytes32 m0; |
||
| 4925 |
bytes32 m1; |
||
| 4926 |
bytes32 m2; |
||
| 4927 |
bytes32 m3; |
||
| 4928 |
bytes32 m4; |
||
| 4929 |
bytes32 m5; |
||
| 4930 |
bytes32 m6; |
||
| 4931 |
bytes32 m7; |
||
| 4932 |
bytes32 m8; |
||
| 4933 |
/// @solidity memory-safe-assembly |
||
| 4934 |
assembly {
|
||
| 4935 |
function writeString(pos, w) {
|
||
| 4936 |
let length := 0 |
||
| 4937 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4938 |
mstore(pos, length) |
||
| 4939 |
let shift := sub(256, shl(3, length)) |
||
| 4940 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4941 |
} |
||
| 4942 |
m0 := mload(0x00) |
||
| 4943 |
m1 := mload(0x20) |
||
| 4944 |
m2 := mload(0x40) |
||
| 4945 |
m3 := mload(0x60) |
||
| 4946 |
m4 := mload(0x80) |
||
| 4947 |
m5 := mload(0xa0) |
||
| 4948 |
m6 := mload(0xc0) |
||
| 4949 |
m7 := mload(0xe0) |
||
| 4950 |
m8 := mload(0x100) |
||
| 4951 |
// Selector of `log(address,string,address,string)`. |
||
| 4952 |
mstore(0x00, 0xf7e36245) |
||
| 4953 |
mstore(0x20, p0) |
||
| 4954 |
mstore(0x40, 0x80) |
||
| 4955 |
mstore(0x60, p2) |
||
| 4956 |
mstore(0x80, 0xc0) |
||
| 4957 |
writeString(0xa0, p1) |
||
| 4958 |
writeString(0xe0, p3) |
||
| 4959 |
} |
||
| 4960 |
_sendLogPayload(0x1c, 0x104); |
||
| 4961 |
/// @solidity memory-safe-assembly |
||
| 4962 |
assembly {
|
||
| 4963 |
mstore(0x00, m0) |
||
| 4964 |
mstore(0x20, m1) |
||
| 4965 |
mstore(0x40, m2) |
||
| 4966 |
mstore(0x60, m3) |
||
| 4967 |
mstore(0x80, m4) |
||
| 4968 |
mstore(0xa0, m5) |
||
| 4969 |
mstore(0xc0, m6) |
||
| 4970 |
mstore(0xe0, m7) |
||
| 4971 |
mstore(0x100, m8) |
||
| 4972 |
} |
||
| 4973 |
} |
||
| 4974 | |||
| 4975 |
function log(address p0, bytes32 p1, bool p2, address p3) internal pure {
|
||
| 4976 |
bytes32 m0; |
||
| 4977 |
bytes32 m1; |
||
| 4978 |
bytes32 m2; |
||
| 4979 |
bytes32 m3; |
||
| 4980 |
bytes32 m4; |
||
| 4981 |
bytes32 m5; |
||
| 4982 |
bytes32 m6; |
||
| 4983 |
/// @solidity memory-safe-assembly |
||
| 4984 |
assembly {
|
||
| 4985 |
function writeString(pos, w) {
|
||
| 4986 |
let length := 0 |
||
| 4987 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 4988 |
mstore(pos, length) |
||
| 4989 |
let shift := sub(256, shl(3, length)) |
||
| 4990 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 4991 |
} |
||
| 4992 |
m0 := mload(0x00) |
||
| 4993 |
m1 := mload(0x20) |
||
| 4994 |
m2 := mload(0x40) |
||
| 4995 |
m3 := mload(0x60) |
||
| 4996 |
m4 := mload(0x80) |
||
| 4997 |
m5 := mload(0xa0) |
||
| 4998 |
m6 := mload(0xc0) |
||
| 4999 |
// Selector of `log(address,string,bool,address)`. |
||
| 5000 |
mstore(0x00, 0x205871c2) |
||
| 5001 |
mstore(0x20, p0) |
||
| 5002 |
mstore(0x40, 0x80) |
||
| 5003 |
mstore(0x60, p2) |
||
| 5004 |
mstore(0x80, p3) |
||
| 5005 |
writeString(0xa0, p1) |
||
| 5006 |
} |
||
| 5007 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5008 |
/// @solidity memory-safe-assembly |
||
| 5009 |
assembly {
|
||
| 5010 |
mstore(0x00, m0) |
||
| 5011 |
mstore(0x20, m1) |
||
| 5012 |
mstore(0x40, m2) |
||
| 5013 |
mstore(0x60, m3) |
||
| 5014 |
mstore(0x80, m4) |
||
| 5015 |
mstore(0xa0, m5) |
||
| 5016 |
mstore(0xc0, m6) |
||
| 5017 |
} |
||
| 5018 |
} |
||
| 5019 | |||
| 5020 |
function log(address p0, bytes32 p1, bool p2, bool p3) internal pure {
|
||
| 5021 |
bytes32 m0; |
||
| 5022 |
bytes32 m1; |
||
| 5023 |
bytes32 m2; |
||
| 5024 |
bytes32 m3; |
||
| 5025 |
bytes32 m4; |
||
| 5026 |
bytes32 m5; |
||
| 5027 |
bytes32 m6; |
||
| 5028 |
/// @solidity memory-safe-assembly |
||
| 5029 |
assembly {
|
||
| 5030 |
function writeString(pos, w) {
|
||
| 5031 |
let length := 0 |
||
| 5032 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5033 |
mstore(pos, length) |
||
| 5034 |
let shift := sub(256, shl(3, length)) |
||
| 5035 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5036 |
} |
||
| 5037 |
m0 := mload(0x00) |
||
| 5038 |
m1 := mload(0x20) |
||
| 5039 |
m2 := mload(0x40) |
||
| 5040 |
m3 := mload(0x60) |
||
| 5041 |
m4 := mload(0x80) |
||
| 5042 |
m5 := mload(0xa0) |
||
| 5043 |
m6 := mload(0xc0) |
||
| 5044 |
// Selector of `log(address,string,bool,bool)`. |
||
| 5045 |
mstore(0x00, 0x5f1d5c9f) |
||
| 5046 |
mstore(0x20, p0) |
||
| 5047 |
mstore(0x40, 0x80) |
||
| 5048 |
mstore(0x60, p2) |
||
| 5049 |
mstore(0x80, p3) |
||
| 5050 |
writeString(0xa0, p1) |
||
| 5051 |
} |
||
| 5052 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5053 |
/// @solidity memory-safe-assembly |
||
| 5054 |
assembly {
|
||
| 5055 |
mstore(0x00, m0) |
||
| 5056 |
mstore(0x20, m1) |
||
| 5057 |
mstore(0x40, m2) |
||
| 5058 |
mstore(0x60, m3) |
||
| 5059 |
mstore(0x80, m4) |
||
| 5060 |
mstore(0xa0, m5) |
||
| 5061 |
mstore(0xc0, m6) |
||
| 5062 |
} |
||
| 5063 |
} |
||
| 5064 | |||
| 5065 |
function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure {
|
||
| 5066 |
bytes32 m0; |
||
| 5067 |
bytes32 m1; |
||
| 5068 |
bytes32 m2; |
||
| 5069 |
bytes32 m3; |
||
| 5070 |
bytes32 m4; |
||
| 5071 |
bytes32 m5; |
||
| 5072 |
bytes32 m6; |
||
| 5073 |
/// @solidity memory-safe-assembly |
||
| 5074 |
assembly {
|
||
| 5075 |
function writeString(pos, w) {
|
||
| 5076 |
let length := 0 |
||
| 5077 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5078 |
mstore(pos, length) |
||
| 5079 |
let shift := sub(256, shl(3, length)) |
||
| 5080 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5081 |
} |
||
| 5082 |
m0 := mload(0x00) |
||
| 5083 |
m1 := mload(0x20) |
||
| 5084 |
m2 := mload(0x40) |
||
| 5085 |
m3 := mload(0x60) |
||
| 5086 |
m4 := mload(0x80) |
||
| 5087 |
m5 := mload(0xa0) |
||
| 5088 |
m6 := mload(0xc0) |
||
| 5089 |
// Selector of `log(address,string,bool,uint256)`. |
||
| 5090 |
mstore(0x00, 0x515e38b6) |
||
| 5091 |
mstore(0x20, p0) |
||
| 5092 |
mstore(0x40, 0x80) |
||
| 5093 |
mstore(0x60, p2) |
||
| 5094 |
mstore(0x80, p3) |
||
| 5095 |
writeString(0xa0, p1) |
||
| 5096 |
} |
||
| 5097 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5098 |
/// @solidity memory-safe-assembly |
||
| 5099 |
assembly {
|
||
| 5100 |
mstore(0x00, m0) |
||
| 5101 |
mstore(0x20, m1) |
||
| 5102 |
mstore(0x40, m2) |
||
| 5103 |
mstore(0x60, m3) |
||
| 5104 |
mstore(0x80, m4) |
||
| 5105 |
mstore(0xa0, m5) |
||
| 5106 |
mstore(0xc0, m6) |
||
| 5107 |
} |
||
| 5108 |
} |
||
| 5109 | |||
| 5110 |
function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
|
||
| 5111 |
bytes32 m0; |
||
| 5112 |
bytes32 m1; |
||
| 5113 |
bytes32 m2; |
||
| 5114 |
bytes32 m3; |
||
| 5115 |
bytes32 m4; |
||
| 5116 |
bytes32 m5; |
||
| 5117 |
bytes32 m6; |
||
| 5118 |
bytes32 m7; |
||
| 5119 |
bytes32 m8; |
||
| 5120 |
/// @solidity memory-safe-assembly |
||
| 5121 |
assembly {
|
||
| 5122 |
function writeString(pos, w) {
|
||
| 5123 |
let length := 0 |
||
| 5124 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5125 |
mstore(pos, length) |
||
| 5126 |
let shift := sub(256, shl(3, length)) |
||
| 5127 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5128 |
} |
||
| 5129 |
m0 := mload(0x00) |
||
| 5130 |
m1 := mload(0x20) |
||
| 5131 |
m2 := mload(0x40) |
||
| 5132 |
m3 := mload(0x60) |
||
| 5133 |
m4 := mload(0x80) |
||
| 5134 |
m5 := mload(0xa0) |
||
| 5135 |
m6 := mload(0xc0) |
||
| 5136 |
m7 := mload(0xe0) |
||
| 5137 |
m8 := mload(0x100) |
||
| 5138 |
// Selector of `log(address,string,bool,string)`. |
||
| 5139 |
mstore(0x00, 0xbc0b61fe) |
||
| 5140 |
mstore(0x20, p0) |
||
| 5141 |
mstore(0x40, 0x80) |
||
| 5142 |
mstore(0x60, p2) |
||
| 5143 |
mstore(0x80, 0xc0) |
||
| 5144 |
writeString(0xa0, p1) |
||
| 5145 |
writeString(0xe0, p3) |
||
| 5146 |
} |
||
| 5147 |
_sendLogPayload(0x1c, 0x104); |
||
| 5148 |
/// @solidity memory-safe-assembly |
||
| 5149 |
assembly {
|
||
| 5150 |
mstore(0x00, m0) |
||
| 5151 |
mstore(0x20, m1) |
||
| 5152 |
mstore(0x40, m2) |
||
| 5153 |
mstore(0x60, m3) |
||
| 5154 |
mstore(0x80, m4) |
||
| 5155 |
mstore(0xa0, m5) |
||
| 5156 |
mstore(0xc0, m6) |
||
| 5157 |
mstore(0xe0, m7) |
||
| 5158 |
mstore(0x100, m8) |
||
| 5159 |
} |
||
| 5160 |
} |
||
| 5161 | |||
| 5162 |
function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure {
|
||
| 5163 |
bytes32 m0; |
||
| 5164 |
bytes32 m1; |
||
| 5165 |
bytes32 m2; |
||
| 5166 |
bytes32 m3; |
||
| 5167 |
bytes32 m4; |
||
| 5168 |
bytes32 m5; |
||
| 5169 |
bytes32 m6; |
||
| 5170 |
/// @solidity memory-safe-assembly |
||
| 5171 |
assembly {
|
||
| 5172 |
function writeString(pos, w) {
|
||
| 5173 |
let length := 0 |
||
| 5174 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5175 |
mstore(pos, length) |
||
| 5176 |
let shift := sub(256, shl(3, length)) |
||
| 5177 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5178 |
} |
||
| 5179 |
m0 := mload(0x00) |
||
| 5180 |
m1 := mload(0x20) |
||
| 5181 |
m2 := mload(0x40) |
||
| 5182 |
m3 := mload(0x60) |
||
| 5183 |
m4 := mload(0x80) |
||
| 5184 |
m5 := mload(0xa0) |
||
| 5185 |
m6 := mload(0xc0) |
||
| 5186 |
// Selector of `log(address,string,uint256,address)`. |
||
| 5187 |
mstore(0x00, 0x63183678) |
||
| 5188 |
mstore(0x20, p0) |
||
| 5189 |
mstore(0x40, 0x80) |
||
| 5190 |
mstore(0x60, p2) |
||
| 5191 |
mstore(0x80, p3) |
||
| 5192 |
writeString(0xa0, p1) |
||
| 5193 |
} |
||
| 5194 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5195 |
/// @solidity memory-safe-assembly |
||
| 5196 |
assembly {
|
||
| 5197 |
mstore(0x00, m0) |
||
| 5198 |
mstore(0x20, m1) |
||
| 5199 |
mstore(0x40, m2) |
||
| 5200 |
mstore(0x60, m3) |
||
| 5201 |
mstore(0x80, m4) |
||
| 5202 |
mstore(0xa0, m5) |
||
| 5203 |
mstore(0xc0, m6) |
||
| 5204 |
} |
||
| 5205 |
} |
||
| 5206 | |||
| 5207 |
function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure {
|
||
| 5208 |
bytes32 m0; |
||
| 5209 |
bytes32 m1; |
||
| 5210 |
bytes32 m2; |
||
| 5211 |
bytes32 m3; |
||
| 5212 |
bytes32 m4; |
||
| 5213 |
bytes32 m5; |
||
| 5214 |
bytes32 m6; |
||
| 5215 |
/// @solidity memory-safe-assembly |
||
| 5216 |
assembly {
|
||
| 5217 |
function writeString(pos, w) {
|
||
| 5218 |
let length := 0 |
||
| 5219 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5220 |
mstore(pos, length) |
||
| 5221 |
let shift := sub(256, shl(3, length)) |
||
| 5222 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5223 |
} |
||
| 5224 |
m0 := mload(0x00) |
||
| 5225 |
m1 := mload(0x20) |
||
| 5226 |
m2 := mload(0x40) |
||
| 5227 |
m3 := mload(0x60) |
||
| 5228 |
m4 := mload(0x80) |
||
| 5229 |
m5 := mload(0xa0) |
||
| 5230 |
m6 := mload(0xc0) |
||
| 5231 |
// Selector of `log(address,string,uint256,bool)`. |
||
| 5232 |
mstore(0x00, 0x0ef7e050) |
||
| 5233 |
mstore(0x20, p0) |
||
| 5234 |
mstore(0x40, 0x80) |
||
| 5235 |
mstore(0x60, p2) |
||
| 5236 |
mstore(0x80, p3) |
||
| 5237 |
writeString(0xa0, p1) |
||
| 5238 |
} |
||
| 5239 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5240 |
/// @solidity memory-safe-assembly |
||
| 5241 |
assembly {
|
||
| 5242 |
mstore(0x00, m0) |
||
| 5243 |
mstore(0x20, m1) |
||
| 5244 |
mstore(0x40, m2) |
||
| 5245 |
mstore(0x60, m3) |
||
| 5246 |
mstore(0x80, m4) |
||
| 5247 |
mstore(0xa0, m5) |
||
| 5248 |
mstore(0xc0, m6) |
||
| 5249 |
} |
||
| 5250 |
} |
||
| 5251 | |||
| 5252 |
function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 5253 |
bytes32 m0; |
||
| 5254 |
bytes32 m1; |
||
| 5255 |
bytes32 m2; |
||
| 5256 |
bytes32 m3; |
||
| 5257 |
bytes32 m4; |
||
| 5258 |
bytes32 m5; |
||
| 5259 |
bytes32 m6; |
||
| 5260 |
/// @solidity memory-safe-assembly |
||
| 5261 |
assembly {
|
||
| 5262 |
function writeString(pos, w) {
|
||
| 5263 |
let length := 0 |
||
| 5264 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5265 |
mstore(pos, length) |
||
| 5266 |
let shift := sub(256, shl(3, length)) |
||
| 5267 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5268 |
} |
||
| 5269 |
m0 := mload(0x00) |
||
| 5270 |
m1 := mload(0x20) |
||
| 5271 |
m2 := mload(0x40) |
||
| 5272 |
m3 := mload(0x60) |
||
| 5273 |
m4 := mload(0x80) |
||
| 5274 |
m5 := mload(0xa0) |
||
| 5275 |
m6 := mload(0xc0) |
||
| 5276 |
// Selector of `log(address,string,uint256,uint256)`. |
||
| 5277 |
mstore(0x00, 0x1dc8e1b8) |
||
| 5278 |
mstore(0x20, p0) |
||
| 5279 |
mstore(0x40, 0x80) |
||
| 5280 |
mstore(0x60, p2) |
||
| 5281 |
mstore(0x80, p3) |
||
| 5282 |
writeString(0xa0, p1) |
||
| 5283 |
} |
||
| 5284 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5285 |
/// @solidity memory-safe-assembly |
||
| 5286 |
assembly {
|
||
| 5287 |
mstore(0x00, m0) |
||
| 5288 |
mstore(0x20, m1) |
||
| 5289 |
mstore(0x40, m2) |
||
| 5290 |
mstore(0x60, m3) |
||
| 5291 |
mstore(0x80, m4) |
||
| 5292 |
mstore(0xa0, m5) |
||
| 5293 |
mstore(0xc0, m6) |
||
| 5294 |
} |
||
| 5295 |
} |
||
| 5296 | |||
| 5297 |
function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 5298 |
bytes32 m0; |
||
| 5299 |
bytes32 m1; |
||
| 5300 |
bytes32 m2; |
||
| 5301 |
bytes32 m3; |
||
| 5302 |
bytes32 m4; |
||
| 5303 |
bytes32 m5; |
||
| 5304 |
bytes32 m6; |
||
| 5305 |
bytes32 m7; |
||
| 5306 |
bytes32 m8; |
||
| 5307 |
/// @solidity memory-safe-assembly |
||
| 5308 |
assembly {
|
||
| 5309 |
function writeString(pos, w) {
|
||
| 5310 |
let length := 0 |
||
| 5311 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5312 |
mstore(pos, length) |
||
| 5313 |
let shift := sub(256, shl(3, length)) |
||
| 5314 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5315 |
} |
||
| 5316 |
m0 := mload(0x00) |
||
| 5317 |
m1 := mload(0x20) |
||
| 5318 |
m2 := mload(0x40) |
||
| 5319 |
m3 := mload(0x60) |
||
| 5320 |
m4 := mload(0x80) |
||
| 5321 |
m5 := mload(0xa0) |
||
| 5322 |
m6 := mload(0xc0) |
||
| 5323 |
m7 := mload(0xe0) |
||
| 5324 |
m8 := mload(0x100) |
||
| 5325 |
// Selector of `log(address,string,uint256,string)`. |
||
| 5326 |
mstore(0x00, 0x448830a8) |
||
| 5327 |
mstore(0x20, p0) |
||
| 5328 |
mstore(0x40, 0x80) |
||
| 5329 |
mstore(0x60, p2) |
||
| 5330 |
mstore(0x80, 0xc0) |
||
| 5331 |
writeString(0xa0, p1) |
||
| 5332 |
writeString(0xe0, p3) |
||
| 5333 |
} |
||
| 5334 |
_sendLogPayload(0x1c, 0x104); |
||
| 5335 |
/// @solidity memory-safe-assembly |
||
| 5336 |
assembly {
|
||
| 5337 |
mstore(0x00, m0) |
||
| 5338 |
mstore(0x20, m1) |
||
| 5339 |
mstore(0x40, m2) |
||
| 5340 |
mstore(0x60, m3) |
||
| 5341 |
mstore(0x80, m4) |
||
| 5342 |
mstore(0xa0, m5) |
||
| 5343 |
mstore(0xc0, m6) |
||
| 5344 |
mstore(0xe0, m7) |
||
| 5345 |
mstore(0x100, m8) |
||
| 5346 |
} |
||
| 5347 |
} |
||
| 5348 | |||
| 5349 |
function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure {
|
||
| 5350 |
bytes32 m0; |
||
| 5351 |
bytes32 m1; |
||
| 5352 |
bytes32 m2; |
||
| 5353 |
bytes32 m3; |
||
| 5354 |
bytes32 m4; |
||
| 5355 |
bytes32 m5; |
||
| 5356 |
bytes32 m6; |
||
| 5357 |
bytes32 m7; |
||
| 5358 |
bytes32 m8; |
||
| 5359 |
/// @solidity memory-safe-assembly |
||
| 5360 |
assembly {
|
||
| 5361 |
function writeString(pos, w) {
|
||
| 5362 |
let length := 0 |
||
| 5363 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5364 |
mstore(pos, length) |
||
| 5365 |
let shift := sub(256, shl(3, length)) |
||
| 5366 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5367 |
} |
||
| 5368 |
m0 := mload(0x00) |
||
| 5369 |
m1 := mload(0x20) |
||
| 5370 |
m2 := mload(0x40) |
||
| 5371 |
m3 := mload(0x60) |
||
| 5372 |
m4 := mload(0x80) |
||
| 5373 |
m5 := mload(0xa0) |
||
| 5374 |
m6 := mload(0xc0) |
||
| 5375 |
m7 := mload(0xe0) |
||
| 5376 |
m8 := mload(0x100) |
||
| 5377 |
// Selector of `log(address,string,string,address)`. |
||
| 5378 |
mstore(0x00, 0xa04e2f87) |
||
| 5379 |
mstore(0x20, p0) |
||
| 5380 |
mstore(0x40, 0x80) |
||
| 5381 |
mstore(0x60, 0xc0) |
||
| 5382 |
mstore(0x80, p3) |
||
| 5383 |
writeString(0xa0, p1) |
||
| 5384 |
writeString(0xe0, p2) |
||
| 5385 |
} |
||
| 5386 |
_sendLogPayload(0x1c, 0x104); |
||
| 5387 |
/// @solidity memory-safe-assembly |
||
| 5388 |
assembly {
|
||
| 5389 |
mstore(0x00, m0) |
||
| 5390 |
mstore(0x20, m1) |
||
| 5391 |
mstore(0x40, m2) |
||
| 5392 |
mstore(0x60, m3) |
||
| 5393 |
mstore(0x80, m4) |
||
| 5394 |
mstore(0xa0, m5) |
||
| 5395 |
mstore(0xc0, m6) |
||
| 5396 |
mstore(0xe0, m7) |
||
| 5397 |
mstore(0x100, m8) |
||
| 5398 |
} |
||
| 5399 |
} |
||
| 5400 | |||
| 5401 |
function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
|
||
| 5402 |
bytes32 m0; |
||
| 5403 |
bytes32 m1; |
||
| 5404 |
bytes32 m2; |
||
| 5405 |
bytes32 m3; |
||
| 5406 |
bytes32 m4; |
||
| 5407 |
bytes32 m5; |
||
| 5408 |
bytes32 m6; |
||
| 5409 |
bytes32 m7; |
||
| 5410 |
bytes32 m8; |
||
| 5411 |
/// @solidity memory-safe-assembly |
||
| 5412 |
assembly {
|
||
| 5413 |
function writeString(pos, w) {
|
||
| 5414 |
let length := 0 |
||
| 5415 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5416 |
mstore(pos, length) |
||
| 5417 |
let shift := sub(256, shl(3, length)) |
||
| 5418 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5419 |
} |
||
| 5420 |
m0 := mload(0x00) |
||
| 5421 |
m1 := mload(0x20) |
||
| 5422 |
m2 := mload(0x40) |
||
| 5423 |
m3 := mload(0x60) |
||
| 5424 |
m4 := mload(0x80) |
||
| 5425 |
m5 := mload(0xa0) |
||
| 5426 |
m6 := mload(0xc0) |
||
| 5427 |
m7 := mload(0xe0) |
||
| 5428 |
m8 := mload(0x100) |
||
| 5429 |
// Selector of `log(address,string,string,bool)`. |
||
| 5430 |
mstore(0x00, 0x35a5071f) |
||
| 5431 |
mstore(0x20, p0) |
||
| 5432 |
mstore(0x40, 0x80) |
||
| 5433 |
mstore(0x60, 0xc0) |
||
| 5434 |
mstore(0x80, p3) |
||
| 5435 |
writeString(0xa0, p1) |
||
| 5436 |
writeString(0xe0, p2) |
||
| 5437 |
} |
||
| 5438 |
_sendLogPayload(0x1c, 0x104); |
||
| 5439 |
/// @solidity memory-safe-assembly |
||
| 5440 |
assembly {
|
||
| 5441 |
mstore(0x00, m0) |
||
| 5442 |
mstore(0x20, m1) |
||
| 5443 |
mstore(0x40, m2) |
||
| 5444 |
mstore(0x60, m3) |
||
| 5445 |
mstore(0x80, m4) |
||
| 5446 |
mstore(0xa0, m5) |
||
| 5447 |
mstore(0xc0, m6) |
||
| 5448 |
mstore(0xe0, m7) |
||
| 5449 |
mstore(0x100, m8) |
||
| 5450 |
} |
||
| 5451 |
} |
||
| 5452 | |||
| 5453 |
function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 5454 |
bytes32 m0; |
||
| 5455 |
bytes32 m1; |
||
| 5456 |
bytes32 m2; |
||
| 5457 |
bytes32 m3; |
||
| 5458 |
bytes32 m4; |
||
| 5459 |
bytes32 m5; |
||
| 5460 |
bytes32 m6; |
||
| 5461 |
bytes32 m7; |
||
| 5462 |
bytes32 m8; |
||
| 5463 |
/// @solidity memory-safe-assembly |
||
| 5464 |
assembly {
|
||
| 5465 |
function writeString(pos, w) {
|
||
| 5466 |
let length := 0 |
||
| 5467 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5468 |
mstore(pos, length) |
||
| 5469 |
let shift := sub(256, shl(3, length)) |
||
| 5470 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5471 |
} |
||
| 5472 |
m0 := mload(0x00) |
||
| 5473 |
m1 := mload(0x20) |
||
| 5474 |
m2 := mload(0x40) |
||
| 5475 |
m3 := mload(0x60) |
||
| 5476 |
m4 := mload(0x80) |
||
| 5477 |
m5 := mload(0xa0) |
||
| 5478 |
m6 := mload(0xc0) |
||
| 5479 |
m7 := mload(0xe0) |
||
| 5480 |
m8 := mload(0x100) |
||
| 5481 |
// Selector of `log(address,string,string,uint256)`. |
||
| 5482 |
mstore(0x00, 0x159f8927) |
||
| 5483 |
mstore(0x20, p0) |
||
| 5484 |
mstore(0x40, 0x80) |
||
| 5485 |
mstore(0x60, 0xc0) |
||
| 5486 |
mstore(0x80, p3) |
||
| 5487 |
writeString(0xa0, p1) |
||
| 5488 |
writeString(0xe0, p2) |
||
| 5489 |
} |
||
| 5490 |
_sendLogPayload(0x1c, 0x104); |
||
| 5491 |
/// @solidity memory-safe-assembly |
||
| 5492 |
assembly {
|
||
| 5493 |
mstore(0x00, m0) |
||
| 5494 |
mstore(0x20, m1) |
||
| 5495 |
mstore(0x40, m2) |
||
| 5496 |
mstore(0x60, m3) |
||
| 5497 |
mstore(0x80, m4) |
||
| 5498 |
mstore(0xa0, m5) |
||
| 5499 |
mstore(0xc0, m6) |
||
| 5500 |
mstore(0xe0, m7) |
||
| 5501 |
mstore(0x100, m8) |
||
| 5502 |
} |
||
| 5503 |
} |
||
| 5504 | |||
| 5505 |
function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 5506 |
bytes32 m0; |
||
| 5507 |
bytes32 m1; |
||
| 5508 |
bytes32 m2; |
||
| 5509 |
bytes32 m3; |
||
| 5510 |
bytes32 m4; |
||
| 5511 |
bytes32 m5; |
||
| 5512 |
bytes32 m6; |
||
| 5513 |
bytes32 m7; |
||
| 5514 |
bytes32 m8; |
||
| 5515 |
bytes32 m9; |
||
| 5516 |
bytes32 m10; |
||
| 5517 |
/// @solidity memory-safe-assembly |
||
| 5518 |
assembly {
|
||
| 5519 |
function writeString(pos, w) {
|
||
| 5520 |
let length := 0 |
||
| 5521 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5522 |
mstore(pos, length) |
||
| 5523 |
let shift := sub(256, shl(3, length)) |
||
| 5524 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5525 |
} |
||
| 5526 |
m0 := mload(0x00) |
||
| 5527 |
m1 := mload(0x20) |
||
| 5528 |
m2 := mload(0x40) |
||
| 5529 |
m3 := mload(0x60) |
||
| 5530 |
m4 := mload(0x80) |
||
| 5531 |
m5 := mload(0xa0) |
||
| 5532 |
m6 := mload(0xc0) |
||
| 5533 |
m7 := mload(0xe0) |
||
| 5534 |
m8 := mload(0x100) |
||
| 5535 |
m9 := mload(0x120) |
||
| 5536 |
m10 := mload(0x140) |
||
| 5537 |
// Selector of `log(address,string,string,string)`. |
||
| 5538 |
mstore(0x00, 0x5d02c50b) |
||
| 5539 |
mstore(0x20, p0) |
||
| 5540 |
mstore(0x40, 0x80) |
||
| 5541 |
mstore(0x60, 0xc0) |
||
| 5542 |
mstore(0x80, 0x100) |
||
| 5543 |
writeString(0xa0, p1) |
||
| 5544 |
writeString(0xe0, p2) |
||
| 5545 |
writeString(0x120, p3) |
||
| 5546 |
} |
||
| 5547 |
_sendLogPayload(0x1c, 0x144); |
||
| 5548 |
/// @solidity memory-safe-assembly |
||
| 5549 |
assembly {
|
||
| 5550 |
mstore(0x00, m0) |
||
| 5551 |
mstore(0x20, m1) |
||
| 5552 |
mstore(0x40, m2) |
||
| 5553 |
mstore(0x60, m3) |
||
| 5554 |
mstore(0x80, m4) |
||
| 5555 |
mstore(0xa0, m5) |
||
| 5556 |
mstore(0xc0, m6) |
||
| 5557 |
mstore(0xe0, m7) |
||
| 5558 |
mstore(0x100, m8) |
||
| 5559 |
mstore(0x120, m9) |
||
| 5560 |
mstore(0x140, m10) |
||
| 5561 |
} |
||
| 5562 |
} |
||
| 5563 | |||
| 5564 |
function log(bool p0, address p1, address p2, address p3) internal pure {
|
||
| 5565 |
bytes32 m0; |
||
| 5566 |
bytes32 m1; |
||
| 5567 |
bytes32 m2; |
||
| 5568 |
bytes32 m3; |
||
| 5569 |
bytes32 m4; |
||
| 5570 |
/// @solidity memory-safe-assembly |
||
| 5571 |
assembly {
|
||
| 5572 |
m0 := mload(0x00) |
||
| 5573 |
m1 := mload(0x20) |
||
| 5574 |
m2 := mload(0x40) |
||
| 5575 |
m3 := mload(0x60) |
||
| 5576 |
m4 := mload(0x80) |
||
| 5577 |
// Selector of `log(bool,address,address,address)`. |
||
| 5578 |
mstore(0x00, 0x1d14d001) |
||
| 5579 |
mstore(0x20, p0) |
||
| 5580 |
mstore(0x40, p1) |
||
| 5581 |
mstore(0x60, p2) |
||
| 5582 |
mstore(0x80, p3) |
||
| 5583 |
} |
||
| 5584 |
_sendLogPayload(0x1c, 0x84); |
||
| 5585 |
/// @solidity memory-safe-assembly |
||
| 5586 |
assembly {
|
||
| 5587 |
mstore(0x00, m0) |
||
| 5588 |
mstore(0x20, m1) |
||
| 5589 |
mstore(0x40, m2) |
||
| 5590 |
mstore(0x60, m3) |
||
| 5591 |
mstore(0x80, m4) |
||
| 5592 |
} |
||
| 5593 |
} |
||
| 5594 | |||
| 5595 |
function log(bool p0, address p1, address p2, bool p3) internal pure {
|
||
| 5596 |
bytes32 m0; |
||
| 5597 |
bytes32 m1; |
||
| 5598 |
bytes32 m2; |
||
| 5599 |
bytes32 m3; |
||
| 5600 |
bytes32 m4; |
||
| 5601 |
/// @solidity memory-safe-assembly |
||
| 5602 |
assembly {
|
||
| 5603 |
m0 := mload(0x00) |
||
| 5604 |
m1 := mload(0x20) |
||
| 5605 |
m2 := mload(0x40) |
||
| 5606 |
m3 := mload(0x60) |
||
| 5607 |
m4 := mload(0x80) |
||
| 5608 |
// Selector of `log(bool,address,address,bool)`. |
||
| 5609 |
mstore(0x00, 0x46600be0) |
||
| 5610 |
mstore(0x20, p0) |
||
| 5611 |
mstore(0x40, p1) |
||
| 5612 |
mstore(0x60, p2) |
||
| 5613 |
mstore(0x80, p3) |
||
| 5614 |
} |
||
| 5615 |
_sendLogPayload(0x1c, 0x84); |
||
| 5616 |
/// @solidity memory-safe-assembly |
||
| 5617 |
assembly {
|
||
| 5618 |
mstore(0x00, m0) |
||
| 5619 |
mstore(0x20, m1) |
||
| 5620 |
mstore(0x40, m2) |
||
| 5621 |
mstore(0x60, m3) |
||
| 5622 |
mstore(0x80, m4) |
||
| 5623 |
} |
||
| 5624 |
} |
||
| 5625 | |||
| 5626 |
function log(bool p0, address p1, address p2, uint256 p3) internal pure {
|
||
| 5627 |
bytes32 m0; |
||
| 5628 |
bytes32 m1; |
||
| 5629 |
bytes32 m2; |
||
| 5630 |
bytes32 m3; |
||
| 5631 |
bytes32 m4; |
||
| 5632 |
/// @solidity memory-safe-assembly |
||
| 5633 |
assembly {
|
||
| 5634 |
m0 := mload(0x00) |
||
| 5635 |
m1 := mload(0x20) |
||
| 5636 |
m2 := mload(0x40) |
||
| 5637 |
m3 := mload(0x60) |
||
| 5638 |
m4 := mload(0x80) |
||
| 5639 |
// Selector of `log(bool,address,address,uint256)`. |
||
| 5640 |
mstore(0x00, 0x0c66d1be) |
||
| 5641 |
mstore(0x20, p0) |
||
| 5642 |
mstore(0x40, p1) |
||
| 5643 |
mstore(0x60, p2) |
||
| 5644 |
mstore(0x80, p3) |
||
| 5645 |
} |
||
| 5646 |
_sendLogPayload(0x1c, 0x84); |
||
| 5647 |
/// @solidity memory-safe-assembly |
||
| 5648 |
assembly {
|
||
| 5649 |
mstore(0x00, m0) |
||
| 5650 |
mstore(0x20, m1) |
||
| 5651 |
mstore(0x40, m2) |
||
| 5652 |
mstore(0x60, m3) |
||
| 5653 |
mstore(0x80, m4) |
||
| 5654 |
} |
||
| 5655 |
} |
||
| 5656 | |||
| 5657 |
function log(bool p0, address p1, address p2, bytes32 p3) internal pure {
|
||
| 5658 |
bytes32 m0; |
||
| 5659 |
bytes32 m1; |
||
| 5660 |
bytes32 m2; |
||
| 5661 |
bytes32 m3; |
||
| 5662 |
bytes32 m4; |
||
| 5663 |
bytes32 m5; |
||
| 5664 |
bytes32 m6; |
||
| 5665 |
/// @solidity memory-safe-assembly |
||
| 5666 |
assembly {
|
||
| 5667 |
function writeString(pos, w) {
|
||
| 5668 |
let length := 0 |
||
| 5669 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5670 |
mstore(pos, length) |
||
| 5671 |
let shift := sub(256, shl(3, length)) |
||
| 5672 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5673 |
} |
||
| 5674 |
m0 := mload(0x00) |
||
| 5675 |
m1 := mload(0x20) |
||
| 5676 |
m2 := mload(0x40) |
||
| 5677 |
m3 := mload(0x60) |
||
| 5678 |
m4 := mload(0x80) |
||
| 5679 |
m5 := mload(0xa0) |
||
| 5680 |
m6 := mload(0xc0) |
||
| 5681 |
// Selector of `log(bool,address,address,string)`. |
||
| 5682 |
mstore(0x00, 0xd812a167) |
||
| 5683 |
mstore(0x20, p0) |
||
| 5684 |
mstore(0x40, p1) |
||
| 5685 |
mstore(0x60, p2) |
||
| 5686 |
mstore(0x80, 0x80) |
||
| 5687 |
writeString(0xa0, p3) |
||
| 5688 |
} |
||
| 5689 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5690 |
/// @solidity memory-safe-assembly |
||
| 5691 |
assembly {
|
||
| 5692 |
mstore(0x00, m0) |
||
| 5693 |
mstore(0x20, m1) |
||
| 5694 |
mstore(0x40, m2) |
||
| 5695 |
mstore(0x60, m3) |
||
| 5696 |
mstore(0x80, m4) |
||
| 5697 |
mstore(0xa0, m5) |
||
| 5698 |
mstore(0xc0, m6) |
||
| 5699 |
} |
||
| 5700 |
} |
||
| 5701 | |||
| 5702 |
function log(bool p0, address p1, bool p2, address p3) internal pure {
|
||
| 5703 |
bytes32 m0; |
||
| 5704 |
bytes32 m1; |
||
| 5705 |
bytes32 m2; |
||
| 5706 |
bytes32 m3; |
||
| 5707 |
bytes32 m4; |
||
| 5708 |
/// @solidity memory-safe-assembly |
||
| 5709 |
assembly {
|
||
| 5710 |
m0 := mload(0x00) |
||
| 5711 |
m1 := mload(0x20) |
||
| 5712 |
m2 := mload(0x40) |
||
| 5713 |
m3 := mload(0x60) |
||
| 5714 |
m4 := mload(0x80) |
||
| 5715 |
// Selector of `log(bool,address,bool,address)`. |
||
| 5716 |
mstore(0x00, 0x1c41a336) |
||
| 5717 |
mstore(0x20, p0) |
||
| 5718 |
mstore(0x40, p1) |
||
| 5719 |
mstore(0x60, p2) |
||
| 5720 |
mstore(0x80, p3) |
||
| 5721 |
} |
||
| 5722 |
_sendLogPayload(0x1c, 0x84); |
||
| 5723 |
/// @solidity memory-safe-assembly |
||
| 5724 |
assembly {
|
||
| 5725 |
mstore(0x00, m0) |
||
| 5726 |
mstore(0x20, m1) |
||
| 5727 |
mstore(0x40, m2) |
||
| 5728 |
mstore(0x60, m3) |
||
| 5729 |
mstore(0x80, m4) |
||
| 5730 |
} |
||
| 5731 |
} |
||
| 5732 | |||
| 5733 |
function log(bool p0, address p1, bool p2, bool p3) internal pure {
|
||
| 5734 |
bytes32 m0; |
||
| 5735 |
bytes32 m1; |
||
| 5736 |
bytes32 m2; |
||
| 5737 |
bytes32 m3; |
||
| 5738 |
bytes32 m4; |
||
| 5739 |
/// @solidity memory-safe-assembly |
||
| 5740 |
assembly {
|
||
| 5741 |
m0 := mload(0x00) |
||
| 5742 |
m1 := mload(0x20) |
||
| 5743 |
m2 := mload(0x40) |
||
| 5744 |
m3 := mload(0x60) |
||
| 5745 |
m4 := mload(0x80) |
||
| 5746 |
// Selector of `log(bool,address,bool,bool)`. |
||
| 5747 |
mstore(0x00, 0x6a9c478b) |
||
| 5748 |
mstore(0x20, p0) |
||
| 5749 |
mstore(0x40, p1) |
||
| 5750 |
mstore(0x60, p2) |
||
| 5751 |
mstore(0x80, p3) |
||
| 5752 |
} |
||
| 5753 |
_sendLogPayload(0x1c, 0x84); |
||
| 5754 |
/// @solidity memory-safe-assembly |
||
| 5755 |
assembly {
|
||
| 5756 |
mstore(0x00, m0) |
||
| 5757 |
mstore(0x20, m1) |
||
| 5758 |
mstore(0x40, m2) |
||
| 5759 |
mstore(0x60, m3) |
||
| 5760 |
mstore(0x80, m4) |
||
| 5761 |
} |
||
| 5762 |
} |
||
| 5763 | |||
| 5764 |
function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
|
||
| 5765 |
bytes32 m0; |
||
| 5766 |
bytes32 m1; |
||
| 5767 |
bytes32 m2; |
||
| 5768 |
bytes32 m3; |
||
| 5769 |
bytes32 m4; |
||
| 5770 |
/// @solidity memory-safe-assembly |
||
| 5771 |
assembly {
|
||
| 5772 |
m0 := mload(0x00) |
||
| 5773 |
m1 := mload(0x20) |
||
| 5774 |
m2 := mload(0x40) |
||
| 5775 |
m3 := mload(0x60) |
||
| 5776 |
m4 := mload(0x80) |
||
| 5777 |
// Selector of `log(bool,address,bool,uint256)`. |
||
| 5778 |
mstore(0x00, 0x07831502) |
||
| 5779 |
mstore(0x20, p0) |
||
| 5780 |
mstore(0x40, p1) |
||
| 5781 |
mstore(0x60, p2) |
||
| 5782 |
mstore(0x80, p3) |
||
| 5783 |
} |
||
| 5784 |
_sendLogPayload(0x1c, 0x84); |
||
| 5785 |
/// @solidity memory-safe-assembly |
||
| 5786 |
assembly {
|
||
| 5787 |
mstore(0x00, m0) |
||
| 5788 |
mstore(0x20, m1) |
||
| 5789 |
mstore(0x40, m2) |
||
| 5790 |
mstore(0x60, m3) |
||
| 5791 |
mstore(0x80, m4) |
||
| 5792 |
} |
||
| 5793 |
} |
||
| 5794 | |||
| 5795 |
function log(bool p0, address p1, bool p2, bytes32 p3) internal pure {
|
||
| 5796 |
bytes32 m0; |
||
| 5797 |
bytes32 m1; |
||
| 5798 |
bytes32 m2; |
||
| 5799 |
bytes32 m3; |
||
| 5800 |
bytes32 m4; |
||
| 5801 |
bytes32 m5; |
||
| 5802 |
bytes32 m6; |
||
| 5803 |
/// @solidity memory-safe-assembly |
||
| 5804 |
assembly {
|
||
| 5805 |
function writeString(pos, w) {
|
||
| 5806 |
let length := 0 |
||
| 5807 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5808 |
mstore(pos, length) |
||
| 5809 |
let shift := sub(256, shl(3, length)) |
||
| 5810 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5811 |
} |
||
| 5812 |
m0 := mload(0x00) |
||
| 5813 |
m1 := mload(0x20) |
||
| 5814 |
m2 := mload(0x40) |
||
| 5815 |
m3 := mload(0x60) |
||
| 5816 |
m4 := mload(0x80) |
||
| 5817 |
m5 := mload(0xa0) |
||
| 5818 |
m6 := mload(0xc0) |
||
| 5819 |
// Selector of `log(bool,address,bool,string)`. |
||
| 5820 |
mstore(0x00, 0x4a66cb34) |
||
| 5821 |
mstore(0x20, p0) |
||
| 5822 |
mstore(0x40, p1) |
||
| 5823 |
mstore(0x60, p2) |
||
| 5824 |
mstore(0x80, 0x80) |
||
| 5825 |
writeString(0xa0, p3) |
||
| 5826 |
} |
||
| 5827 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5828 |
/// @solidity memory-safe-assembly |
||
| 5829 |
assembly {
|
||
| 5830 |
mstore(0x00, m0) |
||
| 5831 |
mstore(0x20, m1) |
||
| 5832 |
mstore(0x40, m2) |
||
| 5833 |
mstore(0x60, m3) |
||
| 5834 |
mstore(0x80, m4) |
||
| 5835 |
mstore(0xa0, m5) |
||
| 5836 |
mstore(0xc0, m6) |
||
| 5837 |
} |
||
| 5838 |
} |
||
| 5839 | |||
| 5840 |
function log(bool p0, address p1, uint256 p2, address p3) internal pure {
|
||
| 5841 |
bytes32 m0; |
||
| 5842 |
bytes32 m1; |
||
| 5843 |
bytes32 m2; |
||
| 5844 |
bytes32 m3; |
||
| 5845 |
bytes32 m4; |
||
| 5846 |
/// @solidity memory-safe-assembly |
||
| 5847 |
assembly {
|
||
| 5848 |
m0 := mload(0x00) |
||
| 5849 |
m1 := mload(0x20) |
||
| 5850 |
m2 := mload(0x40) |
||
| 5851 |
m3 := mload(0x60) |
||
| 5852 |
m4 := mload(0x80) |
||
| 5853 |
// Selector of `log(bool,address,uint256,address)`. |
||
| 5854 |
mstore(0x00, 0x136b05dd) |
||
| 5855 |
mstore(0x20, p0) |
||
| 5856 |
mstore(0x40, p1) |
||
| 5857 |
mstore(0x60, p2) |
||
| 5858 |
mstore(0x80, p3) |
||
| 5859 |
} |
||
| 5860 |
_sendLogPayload(0x1c, 0x84); |
||
| 5861 |
/// @solidity memory-safe-assembly |
||
| 5862 |
assembly {
|
||
| 5863 |
mstore(0x00, m0) |
||
| 5864 |
mstore(0x20, m1) |
||
| 5865 |
mstore(0x40, m2) |
||
| 5866 |
mstore(0x60, m3) |
||
| 5867 |
mstore(0x80, m4) |
||
| 5868 |
} |
||
| 5869 |
} |
||
| 5870 | |||
| 5871 |
function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
|
||
| 5872 |
bytes32 m0; |
||
| 5873 |
bytes32 m1; |
||
| 5874 |
bytes32 m2; |
||
| 5875 |
bytes32 m3; |
||
| 5876 |
bytes32 m4; |
||
| 5877 |
/// @solidity memory-safe-assembly |
||
| 5878 |
assembly {
|
||
| 5879 |
m0 := mload(0x00) |
||
| 5880 |
m1 := mload(0x20) |
||
| 5881 |
m2 := mload(0x40) |
||
| 5882 |
m3 := mload(0x60) |
||
| 5883 |
m4 := mload(0x80) |
||
| 5884 |
// Selector of `log(bool,address,uint256,bool)`. |
||
| 5885 |
mstore(0x00, 0xd6019f1c) |
||
| 5886 |
mstore(0x20, p0) |
||
| 5887 |
mstore(0x40, p1) |
||
| 5888 |
mstore(0x60, p2) |
||
| 5889 |
mstore(0x80, p3) |
||
| 5890 |
} |
||
| 5891 |
_sendLogPayload(0x1c, 0x84); |
||
| 5892 |
/// @solidity memory-safe-assembly |
||
| 5893 |
assembly {
|
||
| 5894 |
mstore(0x00, m0) |
||
| 5895 |
mstore(0x20, m1) |
||
| 5896 |
mstore(0x40, m2) |
||
| 5897 |
mstore(0x60, m3) |
||
| 5898 |
mstore(0x80, m4) |
||
| 5899 |
} |
||
| 5900 |
} |
||
| 5901 | |||
| 5902 |
function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
|
||
| 5903 |
bytes32 m0; |
||
| 5904 |
bytes32 m1; |
||
| 5905 |
bytes32 m2; |
||
| 5906 |
bytes32 m3; |
||
| 5907 |
bytes32 m4; |
||
| 5908 |
/// @solidity memory-safe-assembly |
||
| 5909 |
assembly {
|
||
| 5910 |
m0 := mload(0x00) |
||
| 5911 |
m1 := mload(0x20) |
||
| 5912 |
m2 := mload(0x40) |
||
| 5913 |
m3 := mload(0x60) |
||
| 5914 |
m4 := mload(0x80) |
||
| 5915 |
// Selector of `log(bool,address,uint256,uint256)`. |
||
| 5916 |
mstore(0x00, 0x7bf181a1) |
||
| 5917 |
mstore(0x20, p0) |
||
| 5918 |
mstore(0x40, p1) |
||
| 5919 |
mstore(0x60, p2) |
||
| 5920 |
mstore(0x80, p3) |
||
| 5921 |
} |
||
| 5922 |
_sendLogPayload(0x1c, 0x84); |
||
| 5923 |
/// @solidity memory-safe-assembly |
||
| 5924 |
assembly {
|
||
| 5925 |
mstore(0x00, m0) |
||
| 5926 |
mstore(0x20, m1) |
||
| 5927 |
mstore(0x40, m2) |
||
| 5928 |
mstore(0x60, m3) |
||
| 5929 |
mstore(0x80, m4) |
||
| 5930 |
} |
||
| 5931 |
} |
||
| 5932 | |||
| 5933 |
function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 5934 |
bytes32 m0; |
||
| 5935 |
bytes32 m1; |
||
| 5936 |
bytes32 m2; |
||
| 5937 |
bytes32 m3; |
||
| 5938 |
bytes32 m4; |
||
| 5939 |
bytes32 m5; |
||
| 5940 |
bytes32 m6; |
||
| 5941 |
/// @solidity memory-safe-assembly |
||
| 5942 |
assembly {
|
||
| 5943 |
function writeString(pos, w) {
|
||
| 5944 |
let length := 0 |
||
| 5945 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5946 |
mstore(pos, length) |
||
| 5947 |
let shift := sub(256, shl(3, length)) |
||
| 5948 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5949 |
} |
||
| 5950 |
m0 := mload(0x00) |
||
| 5951 |
m1 := mload(0x20) |
||
| 5952 |
m2 := mload(0x40) |
||
| 5953 |
m3 := mload(0x60) |
||
| 5954 |
m4 := mload(0x80) |
||
| 5955 |
m5 := mload(0xa0) |
||
| 5956 |
m6 := mload(0xc0) |
||
| 5957 |
// Selector of `log(bool,address,uint256,string)`. |
||
| 5958 |
mstore(0x00, 0x51f09ff8) |
||
| 5959 |
mstore(0x20, p0) |
||
| 5960 |
mstore(0x40, p1) |
||
| 5961 |
mstore(0x60, p2) |
||
| 5962 |
mstore(0x80, 0x80) |
||
| 5963 |
writeString(0xa0, p3) |
||
| 5964 |
} |
||
| 5965 |
_sendLogPayload(0x1c, 0xc4); |
||
| 5966 |
/// @solidity memory-safe-assembly |
||
| 5967 |
assembly {
|
||
| 5968 |
mstore(0x00, m0) |
||
| 5969 |
mstore(0x20, m1) |
||
| 5970 |
mstore(0x40, m2) |
||
| 5971 |
mstore(0x60, m3) |
||
| 5972 |
mstore(0x80, m4) |
||
| 5973 |
mstore(0xa0, m5) |
||
| 5974 |
mstore(0xc0, m6) |
||
| 5975 |
} |
||
| 5976 |
} |
||
| 5977 | |||
| 5978 |
function log(bool p0, address p1, bytes32 p2, address p3) internal pure {
|
||
| 5979 |
bytes32 m0; |
||
| 5980 |
bytes32 m1; |
||
| 5981 |
bytes32 m2; |
||
| 5982 |
bytes32 m3; |
||
| 5983 |
bytes32 m4; |
||
| 5984 |
bytes32 m5; |
||
| 5985 |
bytes32 m6; |
||
| 5986 |
/// @solidity memory-safe-assembly |
||
| 5987 |
assembly {
|
||
| 5988 |
function writeString(pos, w) {
|
||
| 5989 |
let length := 0 |
||
| 5990 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 5991 |
mstore(pos, length) |
||
| 5992 |
let shift := sub(256, shl(3, length)) |
||
| 5993 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 5994 |
} |
||
| 5995 |
m0 := mload(0x00) |
||
| 5996 |
m1 := mload(0x20) |
||
| 5997 |
m2 := mload(0x40) |
||
| 5998 |
m3 := mload(0x60) |
||
| 5999 |
m4 := mload(0x80) |
||
| 6000 |
m5 := mload(0xa0) |
||
| 6001 |
m6 := mload(0xc0) |
||
| 6002 |
// Selector of `log(bool,address,string,address)`. |
||
| 6003 |
mstore(0x00, 0x6f7c603e) |
||
| 6004 |
mstore(0x20, p0) |
||
| 6005 |
mstore(0x40, p1) |
||
| 6006 |
mstore(0x60, 0x80) |
||
| 6007 |
mstore(0x80, p3) |
||
| 6008 |
writeString(0xa0, p2) |
||
| 6009 |
} |
||
| 6010 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6011 |
/// @solidity memory-safe-assembly |
||
| 6012 |
assembly {
|
||
| 6013 |
mstore(0x00, m0) |
||
| 6014 |
mstore(0x20, m1) |
||
| 6015 |
mstore(0x40, m2) |
||
| 6016 |
mstore(0x60, m3) |
||
| 6017 |
mstore(0x80, m4) |
||
| 6018 |
mstore(0xa0, m5) |
||
| 6019 |
mstore(0xc0, m6) |
||
| 6020 |
} |
||
| 6021 |
} |
||
| 6022 | |||
| 6023 |
function log(bool p0, address p1, bytes32 p2, bool p3) internal pure {
|
||
| 6024 |
bytes32 m0; |
||
| 6025 |
bytes32 m1; |
||
| 6026 |
bytes32 m2; |
||
| 6027 |
bytes32 m3; |
||
| 6028 |
bytes32 m4; |
||
| 6029 |
bytes32 m5; |
||
| 6030 |
bytes32 m6; |
||
| 6031 |
/// @solidity memory-safe-assembly |
||
| 6032 |
assembly {
|
||
| 6033 |
function writeString(pos, w) {
|
||
| 6034 |
let length := 0 |
||
| 6035 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6036 |
mstore(pos, length) |
||
| 6037 |
let shift := sub(256, shl(3, length)) |
||
| 6038 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6039 |
} |
||
| 6040 |
m0 := mload(0x00) |
||
| 6041 |
m1 := mload(0x20) |
||
| 6042 |
m2 := mload(0x40) |
||
| 6043 |
m3 := mload(0x60) |
||
| 6044 |
m4 := mload(0x80) |
||
| 6045 |
m5 := mload(0xa0) |
||
| 6046 |
m6 := mload(0xc0) |
||
| 6047 |
// Selector of `log(bool,address,string,bool)`. |
||
| 6048 |
mstore(0x00, 0xe2bfd60b) |
||
| 6049 |
mstore(0x20, p0) |
||
| 6050 |
mstore(0x40, p1) |
||
| 6051 |
mstore(0x60, 0x80) |
||
| 6052 |
mstore(0x80, p3) |
||
| 6053 |
writeString(0xa0, p2) |
||
| 6054 |
} |
||
| 6055 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6056 |
/// @solidity memory-safe-assembly |
||
| 6057 |
assembly {
|
||
| 6058 |
mstore(0x00, m0) |
||
| 6059 |
mstore(0x20, m1) |
||
| 6060 |
mstore(0x40, m2) |
||
| 6061 |
mstore(0x60, m3) |
||
| 6062 |
mstore(0x80, m4) |
||
| 6063 |
mstore(0xa0, m5) |
||
| 6064 |
mstore(0xc0, m6) |
||
| 6065 |
} |
||
| 6066 |
} |
||
| 6067 | |||
| 6068 |
function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 6069 |
bytes32 m0; |
||
| 6070 |
bytes32 m1; |
||
| 6071 |
bytes32 m2; |
||
| 6072 |
bytes32 m3; |
||
| 6073 |
bytes32 m4; |
||
| 6074 |
bytes32 m5; |
||
| 6075 |
bytes32 m6; |
||
| 6076 |
/// @solidity memory-safe-assembly |
||
| 6077 |
assembly {
|
||
| 6078 |
function writeString(pos, w) {
|
||
| 6079 |
let length := 0 |
||
| 6080 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6081 |
mstore(pos, length) |
||
| 6082 |
let shift := sub(256, shl(3, length)) |
||
| 6083 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6084 |
} |
||
| 6085 |
m0 := mload(0x00) |
||
| 6086 |
m1 := mload(0x20) |
||
| 6087 |
m2 := mload(0x40) |
||
| 6088 |
m3 := mload(0x60) |
||
| 6089 |
m4 := mload(0x80) |
||
| 6090 |
m5 := mload(0xa0) |
||
| 6091 |
m6 := mload(0xc0) |
||
| 6092 |
// Selector of `log(bool,address,string,uint256)`. |
||
| 6093 |
mstore(0x00, 0xc21f64c7) |
||
| 6094 |
mstore(0x20, p0) |
||
| 6095 |
mstore(0x40, p1) |
||
| 6096 |
mstore(0x60, 0x80) |
||
| 6097 |
mstore(0x80, p3) |
||
| 6098 |
writeString(0xa0, p2) |
||
| 6099 |
} |
||
| 6100 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6101 |
/// @solidity memory-safe-assembly |
||
| 6102 |
assembly {
|
||
| 6103 |
mstore(0x00, m0) |
||
| 6104 |
mstore(0x20, m1) |
||
| 6105 |
mstore(0x40, m2) |
||
| 6106 |
mstore(0x60, m3) |
||
| 6107 |
mstore(0x80, m4) |
||
| 6108 |
mstore(0xa0, m5) |
||
| 6109 |
mstore(0xc0, m6) |
||
| 6110 |
} |
||
| 6111 |
} |
||
| 6112 | |||
| 6113 |
function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 6114 |
bytes32 m0; |
||
| 6115 |
bytes32 m1; |
||
| 6116 |
bytes32 m2; |
||
| 6117 |
bytes32 m3; |
||
| 6118 |
bytes32 m4; |
||
| 6119 |
bytes32 m5; |
||
| 6120 |
bytes32 m6; |
||
| 6121 |
bytes32 m7; |
||
| 6122 |
bytes32 m8; |
||
| 6123 |
/// @solidity memory-safe-assembly |
||
| 6124 |
assembly {
|
||
| 6125 |
function writeString(pos, w) {
|
||
| 6126 |
let length := 0 |
||
| 6127 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6128 |
mstore(pos, length) |
||
| 6129 |
let shift := sub(256, shl(3, length)) |
||
| 6130 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6131 |
} |
||
| 6132 |
m0 := mload(0x00) |
||
| 6133 |
m1 := mload(0x20) |
||
| 6134 |
m2 := mload(0x40) |
||
| 6135 |
m3 := mload(0x60) |
||
| 6136 |
m4 := mload(0x80) |
||
| 6137 |
m5 := mload(0xa0) |
||
| 6138 |
m6 := mload(0xc0) |
||
| 6139 |
m7 := mload(0xe0) |
||
| 6140 |
m8 := mload(0x100) |
||
| 6141 |
// Selector of `log(bool,address,string,string)`. |
||
| 6142 |
mstore(0x00, 0xa73c1db6) |
||
| 6143 |
mstore(0x20, p0) |
||
| 6144 |
mstore(0x40, p1) |
||
| 6145 |
mstore(0x60, 0x80) |
||
| 6146 |
mstore(0x80, 0xc0) |
||
| 6147 |
writeString(0xa0, p2) |
||
| 6148 |
writeString(0xe0, p3) |
||
| 6149 |
} |
||
| 6150 |
_sendLogPayload(0x1c, 0x104); |
||
| 6151 |
/// @solidity memory-safe-assembly |
||
| 6152 |
assembly {
|
||
| 6153 |
mstore(0x00, m0) |
||
| 6154 |
mstore(0x20, m1) |
||
| 6155 |
mstore(0x40, m2) |
||
| 6156 |
mstore(0x60, m3) |
||
| 6157 |
mstore(0x80, m4) |
||
| 6158 |
mstore(0xa0, m5) |
||
| 6159 |
mstore(0xc0, m6) |
||
| 6160 |
mstore(0xe0, m7) |
||
| 6161 |
mstore(0x100, m8) |
||
| 6162 |
} |
||
| 6163 |
} |
||
| 6164 | |||
| 6165 |
function log(bool p0, bool p1, address p2, address p3) internal pure {
|
||
| 6166 |
bytes32 m0; |
||
| 6167 |
bytes32 m1; |
||
| 6168 |
bytes32 m2; |
||
| 6169 |
bytes32 m3; |
||
| 6170 |
bytes32 m4; |
||
| 6171 |
/// @solidity memory-safe-assembly |
||
| 6172 |
assembly {
|
||
| 6173 |
m0 := mload(0x00) |
||
| 6174 |
m1 := mload(0x20) |
||
| 6175 |
m2 := mload(0x40) |
||
| 6176 |
m3 := mload(0x60) |
||
| 6177 |
m4 := mload(0x80) |
||
| 6178 |
// Selector of `log(bool,bool,address,address)`. |
||
| 6179 |
mstore(0x00, 0xf4880ea4) |
||
| 6180 |
mstore(0x20, p0) |
||
| 6181 |
mstore(0x40, p1) |
||
| 6182 |
mstore(0x60, p2) |
||
| 6183 |
mstore(0x80, p3) |
||
| 6184 |
} |
||
| 6185 |
_sendLogPayload(0x1c, 0x84); |
||
| 6186 |
/// @solidity memory-safe-assembly |
||
| 6187 |
assembly {
|
||
| 6188 |
mstore(0x00, m0) |
||
| 6189 |
mstore(0x20, m1) |
||
| 6190 |
mstore(0x40, m2) |
||
| 6191 |
mstore(0x60, m3) |
||
| 6192 |
mstore(0x80, m4) |
||
| 6193 |
} |
||
| 6194 |
} |
||
| 6195 | |||
| 6196 |
function log(bool p0, bool p1, address p2, bool p3) internal pure {
|
||
| 6197 |
bytes32 m0; |
||
| 6198 |
bytes32 m1; |
||
| 6199 |
bytes32 m2; |
||
| 6200 |
bytes32 m3; |
||
| 6201 |
bytes32 m4; |
||
| 6202 |
/// @solidity memory-safe-assembly |
||
| 6203 |
assembly {
|
||
| 6204 |
m0 := mload(0x00) |
||
| 6205 |
m1 := mload(0x20) |
||
| 6206 |
m2 := mload(0x40) |
||
| 6207 |
m3 := mload(0x60) |
||
| 6208 |
m4 := mload(0x80) |
||
| 6209 |
// Selector of `log(bool,bool,address,bool)`. |
||
| 6210 |
mstore(0x00, 0xc0a302d8) |
||
| 6211 |
mstore(0x20, p0) |
||
| 6212 |
mstore(0x40, p1) |
||
| 6213 |
mstore(0x60, p2) |
||
| 6214 |
mstore(0x80, p3) |
||
| 6215 |
} |
||
| 6216 |
_sendLogPayload(0x1c, 0x84); |
||
| 6217 |
/// @solidity memory-safe-assembly |
||
| 6218 |
assembly {
|
||
| 6219 |
mstore(0x00, m0) |
||
| 6220 |
mstore(0x20, m1) |
||
| 6221 |
mstore(0x40, m2) |
||
| 6222 |
mstore(0x60, m3) |
||
| 6223 |
mstore(0x80, m4) |
||
| 6224 |
} |
||
| 6225 |
} |
||
| 6226 | |||
| 6227 |
function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
|
||
| 6228 |
bytes32 m0; |
||
| 6229 |
bytes32 m1; |
||
| 6230 |
bytes32 m2; |
||
| 6231 |
bytes32 m3; |
||
| 6232 |
bytes32 m4; |
||
| 6233 |
/// @solidity memory-safe-assembly |
||
| 6234 |
assembly {
|
||
| 6235 |
m0 := mload(0x00) |
||
| 6236 |
m1 := mload(0x20) |
||
| 6237 |
m2 := mload(0x40) |
||
| 6238 |
m3 := mload(0x60) |
||
| 6239 |
m4 := mload(0x80) |
||
| 6240 |
// Selector of `log(bool,bool,address,uint256)`. |
||
| 6241 |
mstore(0x00, 0x4c123d57) |
||
| 6242 |
mstore(0x20, p0) |
||
| 6243 |
mstore(0x40, p1) |
||
| 6244 |
mstore(0x60, p2) |
||
| 6245 |
mstore(0x80, p3) |
||
| 6246 |
} |
||
| 6247 |
_sendLogPayload(0x1c, 0x84); |
||
| 6248 |
/// @solidity memory-safe-assembly |
||
| 6249 |
assembly {
|
||
| 6250 |
mstore(0x00, m0) |
||
| 6251 |
mstore(0x20, m1) |
||
| 6252 |
mstore(0x40, m2) |
||
| 6253 |
mstore(0x60, m3) |
||
| 6254 |
mstore(0x80, m4) |
||
| 6255 |
} |
||
| 6256 |
} |
||
| 6257 | |||
| 6258 |
function log(bool p0, bool p1, address p2, bytes32 p3) internal pure {
|
||
| 6259 |
bytes32 m0; |
||
| 6260 |
bytes32 m1; |
||
| 6261 |
bytes32 m2; |
||
| 6262 |
bytes32 m3; |
||
| 6263 |
bytes32 m4; |
||
| 6264 |
bytes32 m5; |
||
| 6265 |
bytes32 m6; |
||
| 6266 |
/// @solidity memory-safe-assembly |
||
| 6267 |
assembly {
|
||
| 6268 |
function writeString(pos, w) {
|
||
| 6269 |
let length := 0 |
||
| 6270 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6271 |
mstore(pos, length) |
||
| 6272 |
let shift := sub(256, shl(3, length)) |
||
| 6273 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6274 |
} |
||
| 6275 |
m0 := mload(0x00) |
||
| 6276 |
m1 := mload(0x20) |
||
| 6277 |
m2 := mload(0x40) |
||
| 6278 |
m3 := mload(0x60) |
||
| 6279 |
m4 := mload(0x80) |
||
| 6280 |
m5 := mload(0xa0) |
||
| 6281 |
m6 := mload(0xc0) |
||
| 6282 |
// Selector of `log(bool,bool,address,string)`. |
||
| 6283 |
mstore(0x00, 0xa0a47963) |
||
| 6284 |
mstore(0x20, p0) |
||
| 6285 |
mstore(0x40, p1) |
||
| 6286 |
mstore(0x60, p2) |
||
| 6287 |
mstore(0x80, 0x80) |
||
| 6288 |
writeString(0xa0, p3) |
||
| 6289 |
} |
||
| 6290 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6291 |
/// @solidity memory-safe-assembly |
||
| 6292 |
assembly {
|
||
| 6293 |
mstore(0x00, m0) |
||
| 6294 |
mstore(0x20, m1) |
||
| 6295 |
mstore(0x40, m2) |
||
| 6296 |
mstore(0x60, m3) |
||
| 6297 |
mstore(0x80, m4) |
||
| 6298 |
mstore(0xa0, m5) |
||
| 6299 |
mstore(0xc0, m6) |
||
| 6300 |
} |
||
| 6301 |
} |
||
| 6302 | |||
| 6303 |
function log(bool p0, bool p1, bool p2, address p3) internal pure {
|
||
| 6304 |
bytes32 m0; |
||
| 6305 |
bytes32 m1; |
||
| 6306 |
bytes32 m2; |
||
| 6307 |
bytes32 m3; |
||
| 6308 |
bytes32 m4; |
||
| 6309 |
/// @solidity memory-safe-assembly |
||
| 6310 |
assembly {
|
||
| 6311 |
m0 := mload(0x00) |
||
| 6312 |
m1 := mload(0x20) |
||
| 6313 |
m2 := mload(0x40) |
||
| 6314 |
m3 := mload(0x60) |
||
| 6315 |
m4 := mload(0x80) |
||
| 6316 |
// Selector of `log(bool,bool,bool,address)`. |
||
| 6317 |
mstore(0x00, 0x8c329b1a) |
||
| 6318 |
mstore(0x20, p0) |
||
| 6319 |
mstore(0x40, p1) |
||
| 6320 |
mstore(0x60, p2) |
||
| 6321 |
mstore(0x80, p3) |
||
| 6322 |
} |
||
| 6323 |
_sendLogPayload(0x1c, 0x84); |
||
| 6324 |
/// @solidity memory-safe-assembly |
||
| 6325 |
assembly {
|
||
| 6326 |
mstore(0x00, m0) |
||
| 6327 |
mstore(0x20, m1) |
||
| 6328 |
mstore(0x40, m2) |
||
| 6329 |
mstore(0x60, m3) |
||
| 6330 |
mstore(0x80, m4) |
||
| 6331 |
} |
||
| 6332 |
} |
||
| 6333 | |||
| 6334 |
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 6335 |
bytes32 m0; |
||
| 6336 |
bytes32 m1; |
||
| 6337 |
bytes32 m2; |
||
| 6338 |
bytes32 m3; |
||
| 6339 |
bytes32 m4; |
||
| 6340 |
/// @solidity memory-safe-assembly |
||
| 6341 |
assembly {
|
||
| 6342 |
m0 := mload(0x00) |
||
| 6343 |
m1 := mload(0x20) |
||
| 6344 |
m2 := mload(0x40) |
||
| 6345 |
m3 := mload(0x60) |
||
| 6346 |
m4 := mload(0x80) |
||
| 6347 |
// Selector of `log(bool,bool,bool,bool)`. |
||
| 6348 |
mstore(0x00, 0x3b2a5ce0) |
||
| 6349 |
mstore(0x20, p0) |
||
| 6350 |
mstore(0x40, p1) |
||
| 6351 |
mstore(0x60, p2) |
||
| 6352 |
mstore(0x80, p3) |
||
| 6353 |
} |
||
| 6354 |
_sendLogPayload(0x1c, 0x84); |
||
| 6355 |
/// @solidity memory-safe-assembly |
||
| 6356 |
assembly {
|
||
| 6357 |
mstore(0x00, m0) |
||
| 6358 |
mstore(0x20, m1) |
||
| 6359 |
mstore(0x40, m2) |
||
| 6360 |
mstore(0x60, m3) |
||
| 6361 |
mstore(0x80, m4) |
||
| 6362 |
} |
||
| 6363 |
} |
||
| 6364 | |||
| 6365 |
function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
|
||
| 6366 |
bytes32 m0; |
||
| 6367 |
bytes32 m1; |
||
| 6368 |
bytes32 m2; |
||
| 6369 |
bytes32 m3; |
||
| 6370 |
bytes32 m4; |
||
| 6371 |
/// @solidity memory-safe-assembly |
||
| 6372 |
assembly {
|
||
| 6373 |
m0 := mload(0x00) |
||
| 6374 |
m1 := mload(0x20) |
||
| 6375 |
m2 := mload(0x40) |
||
| 6376 |
m3 := mload(0x60) |
||
| 6377 |
m4 := mload(0x80) |
||
| 6378 |
// Selector of `log(bool,bool,bool,uint256)`. |
||
| 6379 |
mstore(0x00, 0x6d7045c1) |
||
| 6380 |
mstore(0x20, p0) |
||
| 6381 |
mstore(0x40, p1) |
||
| 6382 |
mstore(0x60, p2) |
||
| 6383 |
mstore(0x80, p3) |
||
| 6384 |
} |
||
| 6385 |
_sendLogPayload(0x1c, 0x84); |
||
| 6386 |
/// @solidity memory-safe-assembly |
||
| 6387 |
assembly {
|
||
| 6388 |
mstore(0x00, m0) |
||
| 6389 |
mstore(0x20, m1) |
||
| 6390 |
mstore(0x40, m2) |
||
| 6391 |
mstore(0x60, m3) |
||
| 6392 |
mstore(0x80, m4) |
||
| 6393 |
} |
||
| 6394 |
} |
||
| 6395 | |||
| 6396 |
function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure {
|
||
| 6397 |
bytes32 m0; |
||
| 6398 |
bytes32 m1; |
||
| 6399 |
bytes32 m2; |
||
| 6400 |
bytes32 m3; |
||
| 6401 |
bytes32 m4; |
||
| 6402 |
bytes32 m5; |
||
| 6403 |
bytes32 m6; |
||
| 6404 |
/// @solidity memory-safe-assembly |
||
| 6405 |
assembly {
|
||
| 6406 |
function writeString(pos, w) {
|
||
| 6407 |
let length := 0 |
||
| 6408 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6409 |
mstore(pos, length) |
||
| 6410 |
let shift := sub(256, shl(3, length)) |
||
| 6411 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6412 |
} |
||
| 6413 |
m0 := mload(0x00) |
||
| 6414 |
m1 := mload(0x20) |
||
| 6415 |
m2 := mload(0x40) |
||
| 6416 |
m3 := mload(0x60) |
||
| 6417 |
m4 := mload(0x80) |
||
| 6418 |
m5 := mload(0xa0) |
||
| 6419 |
m6 := mload(0xc0) |
||
| 6420 |
// Selector of `log(bool,bool,bool,string)`. |
||
| 6421 |
mstore(0x00, 0x2ae408d4) |
||
| 6422 |
mstore(0x20, p0) |
||
| 6423 |
mstore(0x40, p1) |
||
| 6424 |
mstore(0x60, p2) |
||
| 6425 |
mstore(0x80, 0x80) |
||
| 6426 |
writeString(0xa0, p3) |
||
| 6427 |
} |
||
| 6428 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6429 |
/// @solidity memory-safe-assembly |
||
| 6430 |
assembly {
|
||
| 6431 |
mstore(0x00, m0) |
||
| 6432 |
mstore(0x20, m1) |
||
| 6433 |
mstore(0x40, m2) |
||
| 6434 |
mstore(0x60, m3) |
||
| 6435 |
mstore(0x80, m4) |
||
| 6436 |
mstore(0xa0, m5) |
||
| 6437 |
mstore(0xc0, m6) |
||
| 6438 |
} |
||
| 6439 |
} |
||
| 6440 | |||
| 6441 |
function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
|
||
| 6442 |
bytes32 m0; |
||
| 6443 |
bytes32 m1; |
||
| 6444 |
bytes32 m2; |
||
| 6445 |
bytes32 m3; |
||
| 6446 |
bytes32 m4; |
||
| 6447 |
/// @solidity memory-safe-assembly |
||
| 6448 |
assembly {
|
||
| 6449 |
m0 := mload(0x00) |
||
| 6450 |
m1 := mload(0x20) |
||
| 6451 |
m2 := mload(0x40) |
||
| 6452 |
m3 := mload(0x60) |
||
| 6453 |
m4 := mload(0x80) |
||
| 6454 |
// Selector of `log(bool,bool,uint256,address)`. |
||
| 6455 |
mstore(0x00, 0x54a7a9a0) |
||
| 6456 |
mstore(0x20, p0) |
||
| 6457 |
mstore(0x40, p1) |
||
| 6458 |
mstore(0x60, p2) |
||
| 6459 |
mstore(0x80, p3) |
||
| 6460 |
} |
||
| 6461 |
_sendLogPayload(0x1c, 0x84); |
||
| 6462 |
/// @solidity memory-safe-assembly |
||
| 6463 |
assembly {
|
||
| 6464 |
mstore(0x00, m0) |
||
| 6465 |
mstore(0x20, m1) |
||
| 6466 |
mstore(0x40, m2) |
||
| 6467 |
mstore(0x60, m3) |
||
| 6468 |
mstore(0x80, m4) |
||
| 6469 |
} |
||
| 6470 |
} |
||
| 6471 | |||
| 6472 |
function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
|
||
| 6473 |
bytes32 m0; |
||
| 6474 |
bytes32 m1; |
||
| 6475 |
bytes32 m2; |
||
| 6476 |
bytes32 m3; |
||
| 6477 |
bytes32 m4; |
||
| 6478 |
/// @solidity memory-safe-assembly |
||
| 6479 |
assembly {
|
||
| 6480 |
m0 := mload(0x00) |
||
| 6481 |
m1 := mload(0x20) |
||
| 6482 |
m2 := mload(0x40) |
||
| 6483 |
m3 := mload(0x60) |
||
| 6484 |
m4 := mload(0x80) |
||
| 6485 |
// Selector of `log(bool,bool,uint256,bool)`. |
||
| 6486 |
mstore(0x00, 0x619e4d0e) |
||
| 6487 |
mstore(0x20, p0) |
||
| 6488 |
mstore(0x40, p1) |
||
| 6489 |
mstore(0x60, p2) |
||
| 6490 |
mstore(0x80, p3) |
||
| 6491 |
} |
||
| 6492 |
_sendLogPayload(0x1c, 0x84); |
||
| 6493 |
/// @solidity memory-safe-assembly |
||
| 6494 |
assembly {
|
||
| 6495 |
mstore(0x00, m0) |
||
| 6496 |
mstore(0x20, m1) |
||
| 6497 |
mstore(0x40, m2) |
||
| 6498 |
mstore(0x60, m3) |
||
| 6499 |
mstore(0x80, m4) |
||
| 6500 |
} |
||
| 6501 |
} |
||
| 6502 | |||
| 6503 |
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
|
||
| 6504 |
bytes32 m0; |
||
| 6505 |
bytes32 m1; |
||
| 6506 |
bytes32 m2; |
||
| 6507 |
bytes32 m3; |
||
| 6508 |
bytes32 m4; |
||
| 6509 |
/// @solidity memory-safe-assembly |
||
| 6510 |
assembly {
|
||
| 6511 |
m0 := mload(0x00) |
||
| 6512 |
m1 := mload(0x20) |
||
| 6513 |
m2 := mload(0x40) |
||
| 6514 |
m3 := mload(0x60) |
||
| 6515 |
m4 := mload(0x80) |
||
| 6516 |
// Selector of `log(bool,bool,uint256,uint256)`. |
||
| 6517 |
mstore(0x00, 0x0bb00eab) |
||
| 6518 |
mstore(0x20, p0) |
||
| 6519 |
mstore(0x40, p1) |
||
| 6520 |
mstore(0x60, p2) |
||
| 6521 |
mstore(0x80, p3) |
||
| 6522 |
} |
||
| 6523 |
_sendLogPayload(0x1c, 0x84); |
||
| 6524 |
/// @solidity memory-safe-assembly |
||
| 6525 |
assembly {
|
||
| 6526 |
mstore(0x00, m0) |
||
| 6527 |
mstore(0x20, m1) |
||
| 6528 |
mstore(0x40, m2) |
||
| 6529 |
mstore(0x60, m3) |
||
| 6530 |
mstore(0x80, m4) |
||
| 6531 |
} |
||
| 6532 |
} |
||
| 6533 | |||
| 6534 |
function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 6535 |
bytes32 m0; |
||
| 6536 |
bytes32 m1; |
||
| 6537 |
bytes32 m2; |
||
| 6538 |
bytes32 m3; |
||
| 6539 |
bytes32 m4; |
||
| 6540 |
bytes32 m5; |
||
| 6541 |
bytes32 m6; |
||
| 6542 |
/// @solidity memory-safe-assembly |
||
| 6543 |
assembly {
|
||
| 6544 |
function writeString(pos, w) {
|
||
| 6545 |
let length := 0 |
||
| 6546 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6547 |
mstore(pos, length) |
||
| 6548 |
let shift := sub(256, shl(3, length)) |
||
| 6549 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6550 |
} |
||
| 6551 |
m0 := mload(0x00) |
||
| 6552 |
m1 := mload(0x20) |
||
| 6553 |
m2 := mload(0x40) |
||
| 6554 |
m3 := mload(0x60) |
||
| 6555 |
m4 := mload(0x80) |
||
| 6556 |
m5 := mload(0xa0) |
||
| 6557 |
m6 := mload(0xc0) |
||
| 6558 |
// Selector of `log(bool,bool,uint256,string)`. |
||
| 6559 |
mstore(0x00, 0x7dd4d0e0) |
||
| 6560 |
mstore(0x20, p0) |
||
| 6561 |
mstore(0x40, p1) |
||
| 6562 |
mstore(0x60, p2) |
||
| 6563 |
mstore(0x80, 0x80) |
||
| 6564 |
writeString(0xa0, p3) |
||
| 6565 |
} |
||
| 6566 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6567 |
/// @solidity memory-safe-assembly |
||
| 6568 |
assembly {
|
||
| 6569 |
mstore(0x00, m0) |
||
| 6570 |
mstore(0x20, m1) |
||
| 6571 |
mstore(0x40, m2) |
||
| 6572 |
mstore(0x60, m3) |
||
| 6573 |
mstore(0x80, m4) |
||
| 6574 |
mstore(0xa0, m5) |
||
| 6575 |
mstore(0xc0, m6) |
||
| 6576 |
} |
||
| 6577 |
} |
||
| 6578 | |||
| 6579 |
function log(bool p0, bool p1, bytes32 p2, address p3) internal pure {
|
||
| 6580 |
bytes32 m0; |
||
| 6581 |
bytes32 m1; |
||
| 6582 |
bytes32 m2; |
||
| 6583 |
bytes32 m3; |
||
| 6584 |
bytes32 m4; |
||
| 6585 |
bytes32 m5; |
||
| 6586 |
bytes32 m6; |
||
| 6587 |
/// @solidity memory-safe-assembly |
||
| 6588 |
assembly {
|
||
| 6589 |
function writeString(pos, w) {
|
||
| 6590 |
let length := 0 |
||
| 6591 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6592 |
mstore(pos, length) |
||
| 6593 |
let shift := sub(256, shl(3, length)) |
||
| 6594 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6595 |
} |
||
| 6596 |
m0 := mload(0x00) |
||
| 6597 |
m1 := mload(0x20) |
||
| 6598 |
m2 := mload(0x40) |
||
| 6599 |
m3 := mload(0x60) |
||
| 6600 |
m4 := mload(0x80) |
||
| 6601 |
m5 := mload(0xa0) |
||
| 6602 |
m6 := mload(0xc0) |
||
| 6603 |
// Selector of `log(bool,bool,string,address)`. |
||
| 6604 |
mstore(0x00, 0xf9ad2b89) |
||
| 6605 |
mstore(0x20, p0) |
||
| 6606 |
mstore(0x40, p1) |
||
| 6607 |
mstore(0x60, 0x80) |
||
| 6608 |
mstore(0x80, p3) |
||
| 6609 |
writeString(0xa0, p2) |
||
| 6610 |
} |
||
| 6611 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6612 |
/// @solidity memory-safe-assembly |
||
| 6613 |
assembly {
|
||
| 6614 |
mstore(0x00, m0) |
||
| 6615 |
mstore(0x20, m1) |
||
| 6616 |
mstore(0x40, m2) |
||
| 6617 |
mstore(0x60, m3) |
||
| 6618 |
mstore(0x80, m4) |
||
| 6619 |
mstore(0xa0, m5) |
||
| 6620 |
mstore(0xc0, m6) |
||
| 6621 |
} |
||
| 6622 |
} |
||
| 6623 | |||
| 6624 |
function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure {
|
||
| 6625 |
bytes32 m0; |
||
| 6626 |
bytes32 m1; |
||
| 6627 |
bytes32 m2; |
||
| 6628 |
bytes32 m3; |
||
| 6629 |
bytes32 m4; |
||
| 6630 |
bytes32 m5; |
||
| 6631 |
bytes32 m6; |
||
| 6632 |
/// @solidity memory-safe-assembly |
||
| 6633 |
assembly {
|
||
| 6634 |
function writeString(pos, w) {
|
||
| 6635 |
let length := 0 |
||
| 6636 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6637 |
mstore(pos, length) |
||
| 6638 |
let shift := sub(256, shl(3, length)) |
||
| 6639 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6640 |
} |
||
| 6641 |
m0 := mload(0x00) |
||
| 6642 |
m1 := mload(0x20) |
||
| 6643 |
m2 := mload(0x40) |
||
| 6644 |
m3 := mload(0x60) |
||
| 6645 |
m4 := mload(0x80) |
||
| 6646 |
m5 := mload(0xa0) |
||
| 6647 |
m6 := mload(0xc0) |
||
| 6648 |
// Selector of `log(bool,bool,string,bool)`. |
||
| 6649 |
mstore(0x00, 0xb857163a) |
||
| 6650 |
mstore(0x20, p0) |
||
| 6651 |
mstore(0x40, p1) |
||
| 6652 |
mstore(0x60, 0x80) |
||
| 6653 |
mstore(0x80, p3) |
||
| 6654 |
writeString(0xa0, p2) |
||
| 6655 |
} |
||
| 6656 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6657 |
/// @solidity memory-safe-assembly |
||
| 6658 |
assembly {
|
||
| 6659 |
mstore(0x00, m0) |
||
| 6660 |
mstore(0x20, m1) |
||
| 6661 |
mstore(0x40, m2) |
||
| 6662 |
mstore(0x60, m3) |
||
| 6663 |
mstore(0x80, m4) |
||
| 6664 |
mstore(0xa0, m5) |
||
| 6665 |
mstore(0xc0, m6) |
||
| 6666 |
} |
||
| 6667 |
} |
||
| 6668 | |||
| 6669 |
function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 6670 |
bytes32 m0; |
||
| 6671 |
bytes32 m1; |
||
| 6672 |
bytes32 m2; |
||
| 6673 |
bytes32 m3; |
||
| 6674 |
bytes32 m4; |
||
| 6675 |
bytes32 m5; |
||
| 6676 |
bytes32 m6; |
||
| 6677 |
/// @solidity memory-safe-assembly |
||
| 6678 |
assembly {
|
||
| 6679 |
function writeString(pos, w) {
|
||
| 6680 |
let length := 0 |
||
| 6681 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6682 |
mstore(pos, length) |
||
| 6683 |
let shift := sub(256, shl(3, length)) |
||
| 6684 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6685 |
} |
||
| 6686 |
m0 := mload(0x00) |
||
| 6687 |
m1 := mload(0x20) |
||
| 6688 |
m2 := mload(0x40) |
||
| 6689 |
m3 := mload(0x60) |
||
| 6690 |
m4 := mload(0x80) |
||
| 6691 |
m5 := mload(0xa0) |
||
| 6692 |
m6 := mload(0xc0) |
||
| 6693 |
// Selector of `log(bool,bool,string,uint256)`. |
||
| 6694 |
mstore(0x00, 0xe3a9ca2f) |
||
| 6695 |
mstore(0x20, p0) |
||
| 6696 |
mstore(0x40, p1) |
||
| 6697 |
mstore(0x60, 0x80) |
||
| 6698 |
mstore(0x80, p3) |
||
| 6699 |
writeString(0xa0, p2) |
||
| 6700 |
} |
||
| 6701 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6702 |
/// @solidity memory-safe-assembly |
||
| 6703 |
assembly {
|
||
| 6704 |
mstore(0x00, m0) |
||
| 6705 |
mstore(0x20, m1) |
||
| 6706 |
mstore(0x40, m2) |
||
| 6707 |
mstore(0x60, m3) |
||
| 6708 |
mstore(0x80, m4) |
||
| 6709 |
mstore(0xa0, m5) |
||
| 6710 |
mstore(0xc0, m6) |
||
| 6711 |
} |
||
| 6712 |
} |
||
| 6713 | |||
| 6714 |
function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 6715 |
bytes32 m0; |
||
| 6716 |
bytes32 m1; |
||
| 6717 |
bytes32 m2; |
||
| 6718 |
bytes32 m3; |
||
| 6719 |
bytes32 m4; |
||
| 6720 |
bytes32 m5; |
||
| 6721 |
bytes32 m6; |
||
| 6722 |
bytes32 m7; |
||
| 6723 |
bytes32 m8; |
||
| 6724 |
/// @solidity memory-safe-assembly |
||
| 6725 |
assembly {
|
||
| 6726 |
function writeString(pos, w) {
|
||
| 6727 |
let length := 0 |
||
| 6728 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6729 |
mstore(pos, length) |
||
| 6730 |
let shift := sub(256, shl(3, length)) |
||
| 6731 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6732 |
} |
||
| 6733 |
m0 := mload(0x00) |
||
| 6734 |
m1 := mload(0x20) |
||
| 6735 |
m2 := mload(0x40) |
||
| 6736 |
m3 := mload(0x60) |
||
| 6737 |
m4 := mload(0x80) |
||
| 6738 |
m5 := mload(0xa0) |
||
| 6739 |
m6 := mload(0xc0) |
||
| 6740 |
m7 := mload(0xe0) |
||
| 6741 |
m8 := mload(0x100) |
||
| 6742 |
// Selector of `log(bool,bool,string,string)`. |
||
| 6743 |
mstore(0x00, 0x6d1e8751) |
||
| 6744 |
mstore(0x20, p0) |
||
| 6745 |
mstore(0x40, p1) |
||
| 6746 |
mstore(0x60, 0x80) |
||
| 6747 |
mstore(0x80, 0xc0) |
||
| 6748 |
writeString(0xa0, p2) |
||
| 6749 |
writeString(0xe0, p3) |
||
| 6750 |
} |
||
| 6751 |
_sendLogPayload(0x1c, 0x104); |
||
| 6752 |
/// @solidity memory-safe-assembly |
||
| 6753 |
assembly {
|
||
| 6754 |
mstore(0x00, m0) |
||
| 6755 |
mstore(0x20, m1) |
||
| 6756 |
mstore(0x40, m2) |
||
| 6757 |
mstore(0x60, m3) |
||
| 6758 |
mstore(0x80, m4) |
||
| 6759 |
mstore(0xa0, m5) |
||
| 6760 |
mstore(0xc0, m6) |
||
| 6761 |
mstore(0xe0, m7) |
||
| 6762 |
mstore(0x100, m8) |
||
| 6763 |
} |
||
| 6764 |
} |
||
| 6765 | |||
| 6766 |
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
|
||
| 6767 |
bytes32 m0; |
||
| 6768 |
bytes32 m1; |
||
| 6769 |
bytes32 m2; |
||
| 6770 |
bytes32 m3; |
||
| 6771 |
bytes32 m4; |
||
| 6772 |
/// @solidity memory-safe-assembly |
||
| 6773 |
assembly {
|
||
| 6774 |
m0 := mload(0x00) |
||
| 6775 |
m1 := mload(0x20) |
||
| 6776 |
m2 := mload(0x40) |
||
| 6777 |
m3 := mload(0x60) |
||
| 6778 |
m4 := mload(0x80) |
||
| 6779 |
// Selector of `log(bool,uint256,address,address)`. |
||
| 6780 |
mstore(0x00, 0x26f560a8) |
||
| 6781 |
mstore(0x20, p0) |
||
| 6782 |
mstore(0x40, p1) |
||
| 6783 |
mstore(0x60, p2) |
||
| 6784 |
mstore(0x80, p3) |
||
| 6785 |
} |
||
| 6786 |
_sendLogPayload(0x1c, 0x84); |
||
| 6787 |
/// @solidity memory-safe-assembly |
||
| 6788 |
assembly {
|
||
| 6789 |
mstore(0x00, m0) |
||
| 6790 |
mstore(0x20, m1) |
||
| 6791 |
mstore(0x40, m2) |
||
| 6792 |
mstore(0x60, m3) |
||
| 6793 |
mstore(0x80, m4) |
||
| 6794 |
} |
||
| 6795 |
} |
||
| 6796 | |||
| 6797 |
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
|
||
| 6798 |
bytes32 m0; |
||
| 6799 |
bytes32 m1; |
||
| 6800 |
bytes32 m2; |
||
| 6801 |
bytes32 m3; |
||
| 6802 |
bytes32 m4; |
||
| 6803 |
/// @solidity memory-safe-assembly |
||
| 6804 |
assembly {
|
||
| 6805 |
m0 := mload(0x00) |
||
| 6806 |
m1 := mload(0x20) |
||
| 6807 |
m2 := mload(0x40) |
||
| 6808 |
m3 := mload(0x60) |
||
| 6809 |
m4 := mload(0x80) |
||
| 6810 |
// Selector of `log(bool,uint256,address,bool)`. |
||
| 6811 |
mstore(0x00, 0xb4c314ff) |
||
| 6812 |
mstore(0x20, p0) |
||
| 6813 |
mstore(0x40, p1) |
||
| 6814 |
mstore(0x60, p2) |
||
| 6815 |
mstore(0x80, p3) |
||
| 6816 |
} |
||
| 6817 |
_sendLogPayload(0x1c, 0x84); |
||
| 6818 |
/// @solidity memory-safe-assembly |
||
| 6819 |
assembly {
|
||
| 6820 |
mstore(0x00, m0) |
||
| 6821 |
mstore(0x20, m1) |
||
| 6822 |
mstore(0x40, m2) |
||
| 6823 |
mstore(0x60, m3) |
||
| 6824 |
mstore(0x80, m4) |
||
| 6825 |
} |
||
| 6826 |
} |
||
| 6827 | |||
| 6828 |
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
|
||
| 6829 |
bytes32 m0; |
||
| 6830 |
bytes32 m1; |
||
| 6831 |
bytes32 m2; |
||
| 6832 |
bytes32 m3; |
||
| 6833 |
bytes32 m4; |
||
| 6834 |
/// @solidity memory-safe-assembly |
||
| 6835 |
assembly {
|
||
| 6836 |
m0 := mload(0x00) |
||
| 6837 |
m1 := mload(0x20) |
||
| 6838 |
m2 := mload(0x40) |
||
| 6839 |
m3 := mload(0x60) |
||
| 6840 |
m4 := mload(0x80) |
||
| 6841 |
// Selector of `log(bool,uint256,address,uint256)`. |
||
| 6842 |
mstore(0x00, 0x1537dc87) |
||
| 6843 |
mstore(0x20, p0) |
||
| 6844 |
mstore(0x40, p1) |
||
| 6845 |
mstore(0x60, p2) |
||
| 6846 |
mstore(0x80, p3) |
||
| 6847 |
} |
||
| 6848 |
_sendLogPayload(0x1c, 0x84); |
||
| 6849 |
/// @solidity memory-safe-assembly |
||
| 6850 |
assembly {
|
||
| 6851 |
mstore(0x00, m0) |
||
| 6852 |
mstore(0x20, m1) |
||
| 6853 |
mstore(0x40, m2) |
||
| 6854 |
mstore(0x60, m3) |
||
| 6855 |
mstore(0x80, m4) |
||
| 6856 |
} |
||
| 6857 |
} |
||
| 6858 | |||
| 6859 |
function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure {
|
||
| 6860 |
bytes32 m0; |
||
| 6861 |
bytes32 m1; |
||
| 6862 |
bytes32 m2; |
||
| 6863 |
bytes32 m3; |
||
| 6864 |
bytes32 m4; |
||
| 6865 |
bytes32 m5; |
||
| 6866 |
bytes32 m6; |
||
| 6867 |
/// @solidity memory-safe-assembly |
||
| 6868 |
assembly {
|
||
| 6869 |
function writeString(pos, w) {
|
||
| 6870 |
let length := 0 |
||
| 6871 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 6872 |
mstore(pos, length) |
||
| 6873 |
let shift := sub(256, shl(3, length)) |
||
| 6874 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 6875 |
} |
||
| 6876 |
m0 := mload(0x00) |
||
| 6877 |
m1 := mload(0x20) |
||
| 6878 |
m2 := mload(0x40) |
||
| 6879 |
m3 := mload(0x60) |
||
| 6880 |
m4 := mload(0x80) |
||
| 6881 |
m5 := mload(0xa0) |
||
| 6882 |
m6 := mload(0xc0) |
||
| 6883 |
// Selector of `log(bool,uint256,address,string)`. |
||
| 6884 |
mstore(0x00, 0x1bb3b09a) |
||
| 6885 |
mstore(0x20, p0) |
||
| 6886 |
mstore(0x40, p1) |
||
| 6887 |
mstore(0x60, p2) |
||
| 6888 |
mstore(0x80, 0x80) |
||
| 6889 |
writeString(0xa0, p3) |
||
| 6890 |
} |
||
| 6891 |
_sendLogPayload(0x1c, 0xc4); |
||
| 6892 |
/// @solidity memory-safe-assembly |
||
| 6893 |
assembly {
|
||
| 6894 |
mstore(0x00, m0) |
||
| 6895 |
mstore(0x20, m1) |
||
| 6896 |
mstore(0x40, m2) |
||
| 6897 |
mstore(0x60, m3) |
||
| 6898 |
mstore(0x80, m4) |
||
| 6899 |
mstore(0xa0, m5) |
||
| 6900 |
mstore(0xc0, m6) |
||
| 6901 |
} |
||
| 6902 |
} |
||
| 6903 | |||
| 6904 |
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
|
||
| 6905 |
bytes32 m0; |
||
| 6906 |
bytes32 m1; |
||
| 6907 |
bytes32 m2; |
||
| 6908 |
bytes32 m3; |
||
| 6909 |
bytes32 m4; |
||
| 6910 |
/// @solidity memory-safe-assembly |
||
| 6911 |
assembly {
|
||
| 6912 |
m0 := mload(0x00) |
||
| 6913 |
m1 := mload(0x20) |
||
| 6914 |
m2 := mload(0x40) |
||
| 6915 |
m3 := mload(0x60) |
||
| 6916 |
m4 := mload(0x80) |
||
| 6917 |
// Selector of `log(bool,uint256,bool,address)`. |
||
| 6918 |
mstore(0x00, 0x9acd3616) |
||
| 6919 |
mstore(0x20, p0) |
||
| 6920 |
mstore(0x40, p1) |
||
| 6921 |
mstore(0x60, p2) |
||
| 6922 |
mstore(0x80, p3) |
||
| 6923 |
} |
||
| 6924 |
_sendLogPayload(0x1c, 0x84); |
||
| 6925 |
/// @solidity memory-safe-assembly |
||
| 6926 |
assembly {
|
||
| 6927 |
mstore(0x00, m0) |
||
| 6928 |
mstore(0x20, m1) |
||
| 6929 |
mstore(0x40, m2) |
||
| 6930 |
mstore(0x60, m3) |
||
| 6931 |
mstore(0x80, m4) |
||
| 6932 |
} |
||
| 6933 |
} |
||
| 6934 | |||
| 6935 |
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
|
||
| 6936 |
bytes32 m0; |
||
| 6937 |
bytes32 m1; |
||
| 6938 |
bytes32 m2; |
||
| 6939 |
bytes32 m3; |
||
| 6940 |
bytes32 m4; |
||
| 6941 |
/// @solidity memory-safe-assembly |
||
| 6942 |
assembly {
|
||
| 6943 |
m0 := mload(0x00) |
||
| 6944 |
m1 := mload(0x20) |
||
| 6945 |
m2 := mload(0x40) |
||
| 6946 |
m3 := mload(0x60) |
||
| 6947 |
m4 := mload(0x80) |
||
| 6948 |
// Selector of `log(bool,uint256,bool,bool)`. |
||
| 6949 |
mstore(0x00, 0xceb5f4d7) |
||
| 6950 |
mstore(0x20, p0) |
||
| 6951 |
mstore(0x40, p1) |
||
| 6952 |
mstore(0x60, p2) |
||
| 6953 |
mstore(0x80, p3) |
||
| 6954 |
} |
||
| 6955 |
_sendLogPayload(0x1c, 0x84); |
||
| 6956 |
/// @solidity memory-safe-assembly |
||
| 6957 |
assembly {
|
||
| 6958 |
mstore(0x00, m0) |
||
| 6959 |
mstore(0x20, m1) |
||
| 6960 |
mstore(0x40, m2) |
||
| 6961 |
mstore(0x60, m3) |
||
| 6962 |
mstore(0x80, m4) |
||
| 6963 |
} |
||
| 6964 |
} |
||
| 6965 | |||
| 6966 |
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
|
||
| 6967 |
bytes32 m0; |
||
| 6968 |
bytes32 m1; |
||
| 6969 |
bytes32 m2; |
||
| 6970 |
bytes32 m3; |
||
| 6971 |
bytes32 m4; |
||
| 6972 |
/// @solidity memory-safe-assembly |
||
| 6973 |
assembly {
|
||
| 6974 |
m0 := mload(0x00) |
||
| 6975 |
m1 := mload(0x20) |
||
| 6976 |
m2 := mload(0x40) |
||
| 6977 |
m3 := mload(0x60) |
||
| 6978 |
m4 := mload(0x80) |
||
| 6979 |
// Selector of `log(bool,uint256,bool,uint256)`. |
||
| 6980 |
mstore(0x00, 0x7f9bbca2) |
||
| 6981 |
mstore(0x20, p0) |
||
| 6982 |
mstore(0x40, p1) |
||
| 6983 |
mstore(0x60, p2) |
||
| 6984 |
mstore(0x80, p3) |
||
| 6985 |
} |
||
| 6986 |
_sendLogPayload(0x1c, 0x84); |
||
| 6987 |
/// @solidity memory-safe-assembly |
||
| 6988 |
assembly {
|
||
| 6989 |
mstore(0x00, m0) |
||
| 6990 |
mstore(0x20, m1) |
||
| 6991 |
mstore(0x40, m2) |
||
| 6992 |
mstore(0x60, m3) |
||
| 6993 |
mstore(0x80, m4) |
||
| 6994 |
} |
||
| 6995 |
} |
||
| 6996 | |||
| 6997 |
function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure {
|
||
| 6998 |
bytes32 m0; |
||
| 6999 |
bytes32 m1; |
||
| 7000 |
bytes32 m2; |
||
| 7001 |
bytes32 m3; |
||
| 7002 |
bytes32 m4; |
||
| 7003 |
bytes32 m5; |
||
| 7004 |
bytes32 m6; |
||
| 7005 |
/// @solidity memory-safe-assembly |
||
| 7006 |
assembly {
|
||
| 7007 |
function writeString(pos, w) {
|
||
| 7008 |
let length := 0 |
||
| 7009 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7010 |
mstore(pos, length) |
||
| 7011 |
let shift := sub(256, shl(3, length)) |
||
| 7012 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7013 |
} |
||
| 7014 |
m0 := mload(0x00) |
||
| 7015 |
m1 := mload(0x20) |
||
| 7016 |
m2 := mload(0x40) |
||
| 7017 |
m3 := mload(0x60) |
||
| 7018 |
m4 := mload(0x80) |
||
| 7019 |
m5 := mload(0xa0) |
||
| 7020 |
m6 := mload(0xc0) |
||
| 7021 |
// Selector of `log(bool,uint256,bool,string)`. |
||
| 7022 |
mstore(0x00, 0x9143dbb1) |
||
| 7023 |
mstore(0x20, p0) |
||
| 7024 |
mstore(0x40, p1) |
||
| 7025 |
mstore(0x60, p2) |
||
| 7026 |
mstore(0x80, 0x80) |
||
| 7027 |
writeString(0xa0, p3) |
||
| 7028 |
} |
||
| 7029 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7030 |
/// @solidity memory-safe-assembly |
||
| 7031 |
assembly {
|
||
| 7032 |
mstore(0x00, m0) |
||
| 7033 |
mstore(0x20, m1) |
||
| 7034 |
mstore(0x40, m2) |
||
| 7035 |
mstore(0x60, m3) |
||
| 7036 |
mstore(0x80, m4) |
||
| 7037 |
mstore(0xa0, m5) |
||
| 7038 |
mstore(0xc0, m6) |
||
| 7039 |
} |
||
| 7040 |
} |
||
| 7041 | |||
| 7042 |
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
|
||
| 7043 |
bytes32 m0; |
||
| 7044 |
bytes32 m1; |
||
| 7045 |
bytes32 m2; |
||
| 7046 |
bytes32 m3; |
||
| 7047 |
bytes32 m4; |
||
| 7048 |
/// @solidity memory-safe-assembly |
||
| 7049 |
assembly {
|
||
| 7050 |
m0 := mload(0x00) |
||
| 7051 |
m1 := mload(0x20) |
||
| 7052 |
m2 := mload(0x40) |
||
| 7053 |
m3 := mload(0x60) |
||
| 7054 |
m4 := mload(0x80) |
||
| 7055 |
// Selector of `log(bool,uint256,uint256,address)`. |
||
| 7056 |
mstore(0x00, 0x00dd87b9) |
||
| 7057 |
mstore(0x20, p0) |
||
| 7058 |
mstore(0x40, p1) |
||
| 7059 |
mstore(0x60, p2) |
||
| 7060 |
mstore(0x80, p3) |
||
| 7061 |
} |
||
| 7062 |
_sendLogPayload(0x1c, 0x84); |
||
| 7063 |
/// @solidity memory-safe-assembly |
||
| 7064 |
assembly {
|
||
| 7065 |
mstore(0x00, m0) |
||
| 7066 |
mstore(0x20, m1) |
||
| 7067 |
mstore(0x40, m2) |
||
| 7068 |
mstore(0x60, m3) |
||
| 7069 |
mstore(0x80, m4) |
||
| 7070 |
} |
||
| 7071 |
} |
||
| 7072 | |||
| 7073 |
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
|
||
| 7074 |
bytes32 m0; |
||
| 7075 |
bytes32 m1; |
||
| 7076 |
bytes32 m2; |
||
| 7077 |
bytes32 m3; |
||
| 7078 |
bytes32 m4; |
||
| 7079 |
/// @solidity memory-safe-assembly |
||
| 7080 |
assembly {
|
||
| 7081 |
m0 := mload(0x00) |
||
| 7082 |
m1 := mload(0x20) |
||
| 7083 |
m2 := mload(0x40) |
||
| 7084 |
m3 := mload(0x60) |
||
| 7085 |
m4 := mload(0x80) |
||
| 7086 |
// Selector of `log(bool,uint256,uint256,bool)`. |
||
| 7087 |
mstore(0x00, 0xbe984353) |
||
| 7088 |
mstore(0x20, p0) |
||
| 7089 |
mstore(0x40, p1) |
||
| 7090 |
mstore(0x60, p2) |
||
| 7091 |
mstore(0x80, p3) |
||
| 7092 |
} |
||
| 7093 |
_sendLogPayload(0x1c, 0x84); |
||
| 7094 |
/// @solidity memory-safe-assembly |
||
| 7095 |
assembly {
|
||
| 7096 |
mstore(0x00, m0) |
||
| 7097 |
mstore(0x20, m1) |
||
| 7098 |
mstore(0x40, m2) |
||
| 7099 |
mstore(0x60, m3) |
||
| 7100 |
mstore(0x80, m4) |
||
| 7101 |
} |
||
| 7102 |
} |
||
| 7103 | |||
| 7104 |
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 7105 |
bytes32 m0; |
||
| 7106 |
bytes32 m1; |
||
| 7107 |
bytes32 m2; |
||
| 7108 |
bytes32 m3; |
||
| 7109 |
bytes32 m4; |
||
| 7110 |
/// @solidity memory-safe-assembly |
||
| 7111 |
assembly {
|
||
| 7112 |
m0 := mload(0x00) |
||
| 7113 |
m1 := mload(0x20) |
||
| 7114 |
m2 := mload(0x40) |
||
| 7115 |
m3 := mload(0x60) |
||
| 7116 |
m4 := mload(0x80) |
||
| 7117 |
// Selector of `log(bool,uint256,uint256,uint256)`. |
||
| 7118 |
mstore(0x00, 0x374bb4b2) |
||
| 7119 |
mstore(0x20, p0) |
||
| 7120 |
mstore(0x40, p1) |
||
| 7121 |
mstore(0x60, p2) |
||
| 7122 |
mstore(0x80, p3) |
||
| 7123 |
} |
||
| 7124 |
_sendLogPayload(0x1c, 0x84); |
||
| 7125 |
/// @solidity memory-safe-assembly |
||
| 7126 |
assembly {
|
||
| 7127 |
mstore(0x00, m0) |
||
| 7128 |
mstore(0x20, m1) |
||
| 7129 |
mstore(0x40, m2) |
||
| 7130 |
mstore(0x60, m3) |
||
| 7131 |
mstore(0x80, m4) |
||
| 7132 |
} |
||
| 7133 |
} |
||
| 7134 | |||
| 7135 |
function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 7136 |
bytes32 m0; |
||
| 7137 |
bytes32 m1; |
||
| 7138 |
bytes32 m2; |
||
| 7139 |
bytes32 m3; |
||
| 7140 |
bytes32 m4; |
||
| 7141 |
bytes32 m5; |
||
| 7142 |
bytes32 m6; |
||
| 7143 |
/// @solidity memory-safe-assembly |
||
| 7144 |
assembly {
|
||
| 7145 |
function writeString(pos, w) {
|
||
| 7146 |
let length := 0 |
||
| 7147 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7148 |
mstore(pos, length) |
||
| 7149 |
let shift := sub(256, shl(3, length)) |
||
| 7150 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7151 |
} |
||
| 7152 |
m0 := mload(0x00) |
||
| 7153 |
m1 := mload(0x20) |
||
| 7154 |
m2 := mload(0x40) |
||
| 7155 |
m3 := mload(0x60) |
||
| 7156 |
m4 := mload(0x80) |
||
| 7157 |
m5 := mload(0xa0) |
||
| 7158 |
m6 := mload(0xc0) |
||
| 7159 |
// Selector of `log(bool,uint256,uint256,string)`. |
||
| 7160 |
mstore(0x00, 0x8e69fb5d) |
||
| 7161 |
mstore(0x20, p0) |
||
| 7162 |
mstore(0x40, p1) |
||
| 7163 |
mstore(0x60, p2) |
||
| 7164 |
mstore(0x80, 0x80) |
||
| 7165 |
writeString(0xa0, p3) |
||
| 7166 |
} |
||
| 7167 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7168 |
/// @solidity memory-safe-assembly |
||
| 7169 |
assembly {
|
||
| 7170 |
mstore(0x00, m0) |
||
| 7171 |
mstore(0x20, m1) |
||
| 7172 |
mstore(0x40, m2) |
||
| 7173 |
mstore(0x60, m3) |
||
| 7174 |
mstore(0x80, m4) |
||
| 7175 |
mstore(0xa0, m5) |
||
| 7176 |
mstore(0xc0, m6) |
||
| 7177 |
} |
||
| 7178 |
} |
||
| 7179 | |||
| 7180 |
function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure {
|
||
| 7181 |
bytes32 m0; |
||
| 7182 |
bytes32 m1; |
||
| 7183 |
bytes32 m2; |
||
| 7184 |
bytes32 m3; |
||
| 7185 |
bytes32 m4; |
||
| 7186 |
bytes32 m5; |
||
| 7187 |
bytes32 m6; |
||
| 7188 |
/// @solidity memory-safe-assembly |
||
| 7189 |
assembly {
|
||
| 7190 |
function writeString(pos, w) {
|
||
| 7191 |
let length := 0 |
||
| 7192 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7193 |
mstore(pos, length) |
||
| 7194 |
let shift := sub(256, shl(3, length)) |
||
| 7195 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7196 |
} |
||
| 7197 |
m0 := mload(0x00) |
||
| 7198 |
m1 := mload(0x20) |
||
| 7199 |
m2 := mload(0x40) |
||
| 7200 |
m3 := mload(0x60) |
||
| 7201 |
m4 := mload(0x80) |
||
| 7202 |
m5 := mload(0xa0) |
||
| 7203 |
m6 := mload(0xc0) |
||
| 7204 |
// Selector of `log(bool,uint256,string,address)`. |
||
| 7205 |
mstore(0x00, 0xfedd1fff) |
||
| 7206 |
mstore(0x20, p0) |
||
| 7207 |
mstore(0x40, p1) |
||
| 7208 |
mstore(0x60, 0x80) |
||
| 7209 |
mstore(0x80, p3) |
||
| 7210 |
writeString(0xa0, p2) |
||
| 7211 |
} |
||
| 7212 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7213 |
/// @solidity memory-safe-assembly |
||
| 7214 |
assembly {
|
||
| 7215 |
mstore(0x00, m0) |
||
| 7216 |
mstore(0x20, m1) |
||
| 7217 |
mstore(0x40, m2) |
||
| 7218 |
mstore(0x60, m3) |
||
| 7219 |
mstore(0x80, m4) |
||
| 7220 |
mstore(0xa0, m5) |
||
| 7221 |
mstore(0xc0, m6) |
||
| 7222 |
} |
||
| 7223 |
} |
||
| 7224 | |||
| 7225 |
function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure {
|
||
| 7226 |
bytes32 m0; |
||
| 7227 |
bytes32 m1; |
||
| 7228 |
bytes32 m2; |
||
| 7229 |
bytes32 m3; |
||
| 7230 |
bytes32 m4; |
||
| 7231 |
bytes32 m5; |
||
| 7232 |
bytes32 m6; |
||
| 7233 |
/// @solidity memory-safe-assembly |
||
| 7234 |
assembly {
|
||
| 7235 |
function writeString(pos, w) {
|
||
| 7236 |
let length := 0 |
||
| 7237 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7238 |
mstore(pos, length) |
||
| 7239 |
let shift := sub(256, shl(3, length)) |
||
| 7240 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7241 |
} |
||
| 7242 |
m0 := mload(0x00) |
||
| 7243 |
m1 := mload(0x20) |
||
| 7244 |
m2 := mload(0x40) |
||
| 7245 |
m3 := mload(0x60) |
||
| 7246 |
m4 := mload(0x80) |
||
| 7247 |
m5 := mload(0xa0) |
||
| 7248 |
m6 := mload(0xc0) |
||
| 7249 |
// Selector of `log(bool,uint256,string,bool)`. |
||
| 7250 |
mstore(0x00, 0xe5e70b2b) |
||
| 7251 |
mstore(0x20, p0) |
||
| 7252 |
mstore(0x40, p1) |
||
| 7253 |
mstore(0x60, 0x80) |
||
| 7254 |
mstore(0x80, p3) |
||
| 7255 |
writeString(0xa0, p2) |
||
| 7256 |
} |
||
| 7257 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7258 |
/// @solidity memory-safe-assembly |
||
| 7259 |
assembly {
|
||
| 7260 |
mstore(0x00, m0) |
||
| 7261 |
mstore(0x20, m1) |
||
| 7262 |
mstore(0x40, m2) |
||
| 7263 |
mstore(0x60, m3) |
||
| 7264 |
mstore(0x80, m4) |
||
| 7265 |
mstore(0xa0, m5) |
||
| 7266 |
mstore(0xc0, m6) |
||
| 7267 |
} |
||
| 7268 |
} |
||
| 7269 | |||
| 7270 |
function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 7271 |
bytes32 m0; |
||
| 7272 |
bytes32 m1; |
||
| 7273 |
bytes32 m2; |
||
| 7274 |
bytes32 m3; |
||
| 7275 |
bytes32 m4; |
||
| 7276 |
bytes32 m5; |
||
| 7277 |
bytes32 m6; |
||
| 7278 |
/// @solidity memory-safe-assembly |
||
| 7279 |
assembly {
|
||
| 7280 |
function writeString(pos, w) {
|
||
| 7281 |
let length := 0 |
||
| 7282 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7283 |
mstore(pos, length) |
||
| 7284 |
let shift := sub(256, shl(3, length)) |
||
| 7285 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7286 |
} |
||
| 7287 |
m0 := mload(0x00) |
||
| 7288 |
m1 := mload(0x20) |
||
| 7289 |
m2 := mload(0x40) |
||
| 7290 |
m3 := mload(0x60) |
||
| 7291 |
m4 := mload(0x80) |
||
| 7292 |
m5 := mload(0xa0) |
||
| 7293 |
m6 := mload(0xc0) |
||
| 7294 |
// Selector of `log(bool,uint256,string,uint256)`. |
||
| 7295 |
mstore(0x00, 0x6a1199e2) |
||
| 7296 |
mstore(0x20, p0) |
||
| 7297 |
mstore(0x40, p1) |
||
| 7298 |
mstore(0x60, 0x80) |
||
| 7299 |
mstore(0x80, p3) |
||
| 7300 |
writeString(0xa0, p2) |
||
| 7301 |
} |
||
| 7302 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7303 |
/// @solidity memory-safe-assembly |
||
| 7304 |
assembly {
|
||
| 7305 |
mstore(0x00, m0) |
||
| 7306 |
mstore(0x20, m1) |
||
| 7307 |
mstore(0x40, m2) |
||
| 7308 |
mstore(0x60, m3) |
||
| 7309 |
mstore(0x80, m4) |
||
| 7310 |
mstore(0xa0, m5) |
||
| 7311 |
mstore(0xc0, m6) |
||
| 7312 |
} |
||
| 7313 |
} |
||
| 7314 | |||
| 7315 |
function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 7316 |
bytes32 m0; |
||
| 7317 |
bytes32 m1; |
||
| 7318 |
bytes32 m2; |
||
| 7319 |
bytes32 m3; |
||
| 7320 |
bytes32 m4; |
||
| 7321 |
bytes32 m5; |
||
| 7322 |
bytes32 m6; |
||
| 7323 |
bytes32 m7; |
||
| 7324 |
bytes32 m8; |
||
| 7325 |
/// @solidity memory-safe-assembly |
||
| 7326 |
assembly {
|
||
| 7327 |
function writeString(pos, w) {
|
||
| 7328 |
let length := 0 |
||
| 7329 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7330 |
mstore(pos, length) |
||
| 7331 |
let shift := sub(256, shl(3, length)) |
||
| 7332 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7333 |
} |
||
| 7334 |
m0 := mload(0x00) |
||
| 7335 |
m1 := mload(0x20) |
||
| 7336 |
m2 := mload(0x40) |
||
| 7337 |
m3 := mload(0x60) |
||
| 7338 |
m4 := mload(0x80) |
||
| 7339 |
m5 := mload(0xa0) |
||
| 7340 |
m6 := mload(0xc0) |
||
| 7341 |
m7 := mload(0xe0) |
||
| 7342 |
m8 := mload(0x100) |
||
| 7343 |
// Selector of `log(bool,uint256,string,string)`. |
||
| 7344 |
mstore(0x00, 0xf5bc2249) |
||
| 7345 |
mstore(0x20, p0) |
||
| 7346 |
mstore(0x40, p1) |
||
| 7347 |
mstore(0x60, 0x80) |
||
| 7348 |
mstore(0x80, 0xc0) |
||
| 7349 |
writeString(0xa0, p2) |
||
| 7350 |
writeString(0xe0, p3) |
||
| 7351 |
} |
||
| 7352 |
_sendLogPayload(0x1c, 0x104); |
||
| 7353 |
/// @solidity memory-safe-assembly |
||
| 7354 |
assembly {
|
||
| 7355 |
mstore(0x00, m0) |
||
| 7356 |
mstore(0x20, m1) |
||
| 7357 |
mstore(0x40, m2) |
||
| 7358 |
mstore(0x60, m3) |
||
| 7359 |
mstore(0x80, m4) |
||
| 7360 |
mstore(0xa0, m5) |
||
| 7361 |
mstore(0xc0, m6) |
||
| 7362 |
mstore(0xe0, m7) |
||
| 7363 |
mstore(0x100, m8) |
||
| 7364 |
} |
||
| 7365 |
} |
||
| 7366 | |||
| 7367 |
function log(bool p0, bytes32 p1, address p2, address p3) internal pure {
|
||
| 7368 |
bytes32 m0; |
||
| 7369 |
bytes32 m1; |
||
| 7370 |
bytes32 m2; |
||
| 7371 |
bytes32 m3; |
||
| 7372 |
bytes32 m4; |
||
| 7373 |
bytes32 m5; |
||
| 7374 |
bytes32 m6; |
||
| 7375 |
/// @solidity memory-safe-assembly |
||
| 7376 |
assembly {
|
||
| 7377 |
function writeString(pos, w) {
|
||
| 7378 |
let length := 0 |
||
| 7379 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7380 |
mstore(pos, length) |
||
| 7381 |
let shift := sub(256, shl(3, length)) |
||
| 7382 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7383 |
} |
||
| 7384 |
m0 := mload(0x00) |
||
| 7385 |
m1 := mload(0x20) |
||
| 7386 |
m2 := mload(0x40) |
||
| 7387 |
m3 := mload(0x60) |
||
| 7388 |
m4 := mload(0x80) |
||
| 7389 |
m5 := mload(0xa0) |
||
| 7390 |
m6 := mload(0xc0) |
||
| 7391 |
// Selector of `log(bool,string,address,address)`. |
||
| 7392 |
mstore(0x00, 0x2b2b18dc) |
||
| 7393 |
mstore(0x20, p0) |
||
| 7394 |
mstore(0x40, 0x80) |
||
| 7395 |
mstore(0x60, p2) |
||
| 7396 |
mstore(0x80, p3) |
||
| 7397 |
writeString(0xa0, p1) |
||
| 7398 |
} |
||
| 7399 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7400 |
/// @solidity memory-safe-assembly |
||
| 7401 |
assembly {
|
||
| 7402 |
mstore(0x00, m0) |
||
| 7403 |
mstore(0x20, m1) |
||
| 7404 |
mstore(0x40, m2) |
||
| 7405 |
mstore(0x60, m3) |
||
| 7406 |
mstore(0x80, m4) |
||
| 7407 |
mstore(0xa0, m5) |
||
| 7408 |
mstore(0xc0, m6) |
||
| 7409 |
} |
||
| 7410 |
} |
||
| 7411 | |||
| 7412 |
function log(bool p0, bytes32 p1, address p2, bool p3) internal pure {
|
||
| 7413 |
bytes32 m0; |
||
| 7414 |
bytes32 m1; |
||
| 7415 |
bytes32 m2; |
||
| 7416 |
bytes32 m3; |
||
| 7417 |
bytes32 m4; |
||
| 7418 |
bytes32 m5; |
||
| 7419 |
bytes32 m6; |
||
| 7420 |
/// @solidity memory-safe-assembly |
||
| 7421 |
assembly {
|
||
| 7422 |
function writeString(pos, w) {
|
||
| 7423 |
let length := 0 |
||
| 7424 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7425 |
mstore(pos, length) |
||
| 7426 |
let shift := sub(256, shl(3, length)) |
||
| 7427 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7428 |
} |
||
| 7429 |
m0 := mload(0x00) |
||
| 7430 |
m1 := mload(0x20) |
||
| 7431 |
m2 := mload(0x40) |
||
| 7432 |
m3 := mload(0x60) |
||
| 7433 |
m4 := mload(0x80) |
||
| 7434 |
m5 := mload(0xa0) |
||
| 7435 |
m6 := mload(0xc0) |
||
| 7436 |
// Selector of `log(bool,string,address,bool)`. |
||
| 7437 |
mstore(0x00, 0x6dd434ca) |
||
| 7438 |
mstore(0x20, p0) |
||
| 7439 |
mstore(0x40, 0x80) |
||
| 7440 |
mstore(0x60, p2) |
||
| 7441 |
mstore(0x80, p3) |
||
| 7442 |
writeString(0xa0, p1) |
||
| 7443 |
} |
||
| 7444 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7445 |
/// @solidity memory-safe-assembly |
||
| 7446 |
assembly {
|
||
| 7447 |
mstore(0x00, m0) |
||
| 7448 |
mstore(0x20, m1) |
||
| 7449 |
mstore(0x40, m2) |
||
| 7450 |
mstore(0x60, m3) |
||
| 7451 |
mstore(0x80, m4) |
||
| 7452 |
mstore(0xa0, m5) |
||
| 7453 |
mstore(0xc0, m6) |
||
| 7454 |
} |
||
| 7455 |
} |
||
| 7456 | |||
| 7457 |
function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure {
|
||
| 7458 |
bytes32 m0; |
||
| 7459 |
bytes32 m1; |
||
| 7460 |
bytes32 m2; |
||
| 7461 |
bytes32 m3; |
||
| 7462 |
bytes32 m4; |
||
| 7463 |
bytes32 m5; |
||
| 7464 |
bytes32 m6; |
||
| 7465 |
/// @solidity memory-safe-assembly |
||
| 7466 |
assembly {
|
||
| 7467 |
function writeString(pos, w) {
|
||
| 7468 |
let length := 0 |
||
| 7469 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7470 |
mstore(pos, length) |
||
| 7471 |
let shift := sub(256, shl(3, length)) |
||
| 7472 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7473 |
} |
||
| 7474 |
m0 := mload(0x00) |
||
| 7475 |
m1 := mload(0x20) |
||
| 7476 |
m2 := mload(0x40) |
||
| 7477 |
m3 := mload(0x60) |
||
| 7478 |
m4 := mload(0x80) |
||
| 7479 |
m5 := mload(0xa0) |
||
| 7480 |
m6 := mload(0xc0) |
||
| 7481 |
// Selector of `log(bool,string,address,uint256)`. |
||
| 7482 |
mstore(0x00, 0xa5cada94) |
||
| 7483 |
mstore(0x20, p0) |
||
| 7484 |
mstore(0x40, 0x80) |
||
| 7485 |
mstore(0x60, p2) |
||
| 7486 |
mstore(0x80, p3) |
||
| 7487 |
writeString(0xa0, p1) |
||
| 7488 |
} |
||
| 7489 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7490 |
/// @solidity memory-safe-assembly |
||
| 7491 |
assembly {
|
||
| 7492 |
mstore(0x00, m0) |
||
| 7493 |
mstore(0x20, m1) |
||
| 7494 |
mstore(0x40, m2) |
||
| 7495 |
mstore(0x60, m3) |
||
| 7496 |
mstore(0x80, m4) |
||
| 7497 |
mstore(0xa0, m5) |
||
| 7498 |
mstore(0xc0, m6) |
||
| 7499 |
} |
||
| 7500 |
} |
||
| 7501 | |||
| 7502 |
function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure {
|
||
| 7503 |
bytes32 m0; |
||
| 7504 |
bytes32 m1; |
||
| 7505 |
bytes32 m2; |
||
| 7506 |
bytes32 m3; |
||
| 7507 |
bytes32 m4; |
||
| 7508 |
bytes32 m5; |
||
| 7509 |
bytes32 m6; |
||
| 7510 |
bytes32 m7; |
||
| 7511 |
bytes32 m8; |
||
| 7512 |
/// @solidity memory-safe-assembly |
||
| 7513 |
assembly {
|
||
| 7514 |
function writeString(pos, w) {
|
||
| 7515 |
let length := 0 |
||
| 7516 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7517 |
mstore(pos, length) |
||
| 7518 |
let shift := sub(256, shl(3, length)) |
||
| 7519 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7520 |
} |
||
| 7521 |
m0 := mload(0x00) |
||
| 7522 |
m1 := mload(0x20) |
||
| 7523 |
m2 := mload(0x40) |
||
| 7524 |
m3 := mload(0x60) |
||
| 7525 |
m4 := mload(0x80) |
||
| 7526 |
m5 := mload(0xa0) |
||
| 7527 |
m6 := mload(0xc0) |
||
| 7528 |
m7 := mload(0xe0) |
||
| 7529 |
m8 := mload(0x100) |
||
| 7530 |
// Selector of `log(bool,string,address,string)`. |
||
| 7531 |
mstore(0x00, 0x12d6c788) |
||
| 7532 |
mstore(0x20, p0) |
||
| 7533 |
mstore(0x40, 0x80) |
||
| 7534 |
mstore(0x60, p2) |
||
| 7535 |
mstore(0x80, 0xc0) |
||
| 7536 |
writeString(0xa0, p1) |
||
| 7537 |
writeString(0xe0, p3) |
||
| 7538 |
} |
||
| 7539 |
_sendLogPayload(0x1c, 0x104); |
||
| 7540 |
/// @solidity memory-safe-assembly |
||
| 7541 |
assembly {
|
||
| 7542 |
mstore(0x00, m0) |
||
| 7543 |
mstore(0x20, m1) |
||
| 7544 |
mstore(0x40, m2) |
||
| 7545 |
mstore(0x60, m3) |
||
| 7546 |
mstore(0x80, m4) |
||
| 7547 |
mstore(0xa0, m5) |
||
| 7548 |
mstore(0xc0, m6) |
||
| 7549 |
mstore(0xe0, m7) |
||
| 7550 |
mstore(0x100, m8) |
||
| 7551 |
} |
||
| 7552 |
} |
||
| 7553 | |||
| 7554 |
function log(bool p0, bytes32 p1, bool p2, address p3) internal pure {
|
||
| 7555 |
bytes32 m0; |
||
| 7556 |
bytes32 m1; |
||
| 7557 |
bytes32 m2; |
||
| 7558 |
bytes32 m3; |
||
| 7559 |
bytes32 m4; |
||
| 7560 |
bytes32 m5; |
||
| 7561 |
bytes32 m6; |
||
| 7562 |
/// @solidity memory-safe-assembly |
||
| 7563 |
assembly {
|
||
| 7564 |
function writeString(pos, w) {
|
||
| 7565 |
let length := 0 |
||
| 7566 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7567 |
mstore(pos, length) |
||
| 7568 |
let shift := sub(256, shl(3, length)) |
||
| 7569 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7570 |
} |
||
| 7571 |
m0 := mload(0x00) |
||
| 7572 |
m1 := mload(0x20) |
||
| 7573 |
m2 := mload(0x40) |
||
| 7574 |
m3 := mload(0x60) |
||
| 7575 |
m4 := mload(0x80) |
||
| 7576 |
m5 := mload(0xa0) |
||
| 7577 |
m6 := mload(0xc0) |
||
| 7578 |
// Selector of `log(bool,string,bool,address)`. |
||
| 7579 |
mstore(0x00, 0x538e06ab) |
||
| 7580 |
mstore(0x20, p0) |
||
| 7581 |
mstore(0x40, 0x80) |
||
| 7582 |
mstore(0x60, p2) |
||
| 7583 |
mstore(0x80, p3) |
||
| 7584 |
writeString(0xa0, p1) |
||
| 7585 |
} |
||
| 7586 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7587 |
/// @solidity memory-safe-assembly |
||
| 7588 |
assembly {
|
||
| 7589 |
mstore(0x00, m0) |
||
| 7590 |
mstore(0x20, m1) |
||
| 7591 |
mstore(0x40, m2) |
||
| 7592 |
mstore(0x60, m3) |
||
| 7593 |
mstore(0x80, m4) |
||
| 7594 |
mstore(0xa0, m5) |
||
| 7595 |
mstore(0xc0, m6) |
||
| 7596 |
} |
||
| 7597 |
} |
||
| 7598 | |||
| 7599 |
function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure {
|
||
| 7600 |
bytes32 m0; |
||
| 7601 |
bytes32 m1; |
||
| 7602 |
bytes32 m2; |
||
| 7603 |
bytes32 m3; |
||
| 7604 |
bytes32 m4; |
||
| 7605 |
bytes32 m5; |
||
| 7606 |
bytes32 m6; |
||
| 7607 |
/// @solidity memory-safe-assembly |
||
| 7608 |
assembly {
|
||
| 7609 |
function writeString(pos, w) {
|
||
| 7610 |
let length := 0 |
||
| 7611 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7612 |
mstore(pos, length) |
||
| 7613 |
let shift := sub(256, shl(3, length)) |
||
| 7614 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7615 |
} |
||
| 7616 |
m0 := mload(0x00) |
||
| 7617 |
m1 := mload(0x20) |
||
| 7618 |
m2 := mload(0x40) |
||
| 7619 |
m3 := mload(0x60) |
||
| 7620 |
m4 := mload(0x80) |
||
| 7621 |
m5 := mload(0xa0) |
||
| 7622 |
m6 := mload(0xc0) |
||
| 7623 |
// Selector of `log(bool,string,bool,bool)`. |
||
| 7624 |
mstore(0x00, 0xdc5e935b) |
||
| 7625 |
mstore(0x20, p0) |
||
| 7626 |
mstore(0x40, 0x80) |
||
| 7627 |
mstore(0x60, p2) |
||
| 7628 |
mstore(0x80, p3) |
||
| 7629 |
writeString(0xa0, p1) |
||
| 7630 |
} |
||
| 7631 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7632 |
/// @solidity memory-safe-assembly |
||
| 7633 |
assembly {
|
||
| 7634 |
mstore(0x00, m0) |
||
| 7635 |
mstore(0x20, m1) |
||
| 7636 |
mstore(0x40, m2) |
||
| 7637 |
mstore(0x60, m3) |
||
| 7638 |
mstore(0x80, m4) |
||
| 7639 |
mstore(0xa0, m5) |
||
| 7640 |
mstore(0xc0, m6) |
||
| 7641 |
} |
||
| 7642 |
} |
||
| 7643 | |||
| 7644 |
function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure {
|
||
| 7645 |
bytes32 m0; |
||
| 7646 |
bytes32 m1; |
||
| 7647 |
bytes32 m2; |
||
| 7648 |
bytes32 m3; |
||
| 7649 |
bytes32 m4; |
||
| 7650 |
bytes32 m5; |
||
| 7651 |
bytes32 m6; |
||
| 7652 |
/// @solidity memory-safe-assembly |
||
| 7653 |
assembly {
|
||
| 7654 |
function writeString(pos, w) {
|
||
| 7655 |
let length := 0 |
||
| 7656 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7657 |
mstore(pos, length) |
||
| 7658 |
let shift := sub(256, shl(3, length)) |
||
| 7659 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7660 |
} |
||
| 7661 |
m0 := mload(0x00) |
||
| 7662 |
m1 := mload(0x20) |
||
| 7663 |
m2 := mload(0x40) |
||
| 7664 |
m3 := mload(0x60) |
||
| 7665 |
m4 := mload(0x80) |
||
| 7666 |
m5 := mload(0xa0) |
||
| 7667 |
m6 := mload(0xc0) |
||
| 7668 |
// Selector of `log(bool,string,bool,uint256)`. |
||
| 7669 |
mstore(0x00, 0x1606a393) |
||
| 7670 |
mstore(0x20, p0) |
||
| 7671 |
mstore(0x40, 0x80) |
||
| 7672 |
mstore(0x60, p2) |
||
| 7673 |
mstore(0x80, p3) |
||
| 7674 |
writeString(0xa0, p1) |
||
| 7675 |
} |
||
| 7676 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7677 |
/// @solidity memory-safe-assembly |
||
| 7678 |
assembly {
|
||
| 7679 |
mstore(0x00, m0) |
||
| 7680 |
mstore(0x20, m1) |
||
| 7681 |
mstore(0x40, m2) |
||
| 7682 |
mstore(0x60, m3) |
||
| 7683 |
mstore(0x80, m4) |
||
| 7684 |
mstore(0xa0, m5) |
||
| 7685 |
mstore(0xc0, m6) |
||
| 7686 |
} |
||
| 7687 |
} |
||
| 7688 | |||
| 7689 |
function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
|
||
| 7690 |
bytes32 m0; |
||
| 7691 |
bytes32 m1; |
||
| 7692 |
bytes32 m2; |
||
| 7693 |
bytes32 m3; |
||
| 7694 |
bytes32 m4; |
||
| 7695 |
bytes32 m5; |
||
| 7696 |
bytes32 m6; |
||
| 7697 |
bytes32 m7; |
||
| 7698 |
bytes32 m8; |
||
| 7699 |
/// @solidity memory-safe-assembly |
||
| 7700 |
assembly {
|
||
| 7701 |
function writeString(pos, w) {
|
||
| 7702 |
let length := 0 |
||
| 7703 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7704 |
mstore(pos, length) |
||
| 7705 |
let shift := sub(256, shl(3, length)) |
||
| 7706 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7707 |
} |
||
| 7708 |
m0 := mload(0x00) |
||
| 7709 |
m1 := mload(0x20) |
||
| 7710 |
m2 := mload(0x40) |
||
| 7711 |
m3 := mload(0x60) |
||
| 7712 |
m4 := mload(0x80) |
||
| 7713 |
m5 := mload(0xa0) |
||
| 7714 |
m6 := mload(0xc0) |
||
| 7715 |
m7 := mload(0xe0) |
||
| 7716 |
m8 := mload(0x100) |
||
| 7717 |
// Selector of `log(bool,string,bool,string)`. |
||
| 7718 |
mstore(0x00, 0x483d0416) |
||
| 7719 |
mstore(0x20, p0) |
||
| 7720 |
mstore(0x40, 0x80) |
||
| 7721 |
mstore(0x60, p2) |
||
| 7722 |
mstore(0x80, 0xc0) |
||
| 7723 |
writeString(0xa0, p1) |
||
| 7724 |
writeString(0xe0, p3) |
||
| 7725 |
} |
||
| 7726 |
_sendLogPayload(0x1c, 0x104); |
||
| 7727 |
/// @solidity memory-safe-assembly |
||
| 7728 |
assembly {
|
||
| 7729 |
mstore(0x00, m0) |
||
| 7730 |
mstore(0x20, m1) |
||
| 7731 |
mstore(0x40, m2) |
||
| 7732 |
mstore(0x60, m3) |
||
| 7733 |
mstore(0x80, m4) |
||
| 7734 |
mstore(0xa0, m5) |
||
| 7735 |
mstore(0xc0, m6) |
||
| 7736 |
mstore(0xe0, m7) |
||
| 7737 |
mstore(0x100, m8) |
||
| 7738 |
} |
||
| 7739 |
} |
||
| 7740 | |||
| 7741 |
function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure {
|
||
| 7742 |
bytes32 m0; |
||
| 7743 |
bytes32 m1; |
||
| 7744 |
bytes32 m2; |
||
| 7745 |
bytes32 m3; |
||
| 7746 |
bytes32 m4; |
||
| 7747 |
bytes32 m5; |
||
| 7748 |
bytes32 m6; |
||
| 7749 |
/// @solidity memory-safe-assembly |
||
| 7750 |
assembly {
|
||
| 7751 |
function writeString(pos, w) {
|
||
| 7752 |
let length := 0 |
||
| 7753 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7754 |
mstore(pos, length) |
||
| 7755 |
let shift := sub(256, shl(3, length)) |
||
| 7756 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7757 |
} |
||
| 7758 |
m0 := mload(0x00) |
||
| 7759 |
m1 := mload(0x20) |
||
| 7760 |
m2 := mload(0x40) |
||
| 7761 |
m3 := mload(0x60) |
||
| 7762 |
m4 := mload(0x80) |
||
| 7763 |
m5 := mload(0xa0) |
||
| 7764 |
m6 := mload(0xc0) |
||
| 7765 |
// Selector of `log(bool,string,uint256,address)`. |
||
| 7766 |
mstore(0x00, 0x1596a1ce) |
||
| 7767 |
mstore(0x20, p0) |
||
| 7768 |
mstore(0x40, 0x80) |
||
| 7769 |
mstore(0x60, p2) |
||
| 7770 |
mstore(0x80, p3) |
||
| 7771 |
writeString(0xa0, p1) |
||
| 7772 |
} |
||
| 7773 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7774 |
/// @solidity memory-safe-assembly |
||
| 7775 |
assembly {
|
||
| 7776 |
mstore(0x00, m0) |
||
| 7777 |
mstore(0x20, m1) |
||
| 7778 |
mstore(0x40, m2) |
||
| 7779 |
mstore(0x60, m3) |
||
| 7780 |
mstore(0x80, m4) |
||
| 7781 |
mstore(0xa0, m5) |
||
| 7782 |
mstore(0xc0, m6) |
||
| 7783 |
} |
||
| 7784 |
} |
||
| 7785 | |||
| 7786 |
function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure {
|
||
| 7787 |
bytes32 m0; |
||
| 7788 |
bytes32 m1; |
||
| 7789 |
bytes32 m2; |
||
| 7790 |
bytes32 m3; |
||
| 7791 |
bytes32 m4; |
||
| 7792 |
bytes32 m5; |
||
| 7793 |
bytes32 m6; |
||
| 7794 |
/// @solidity memory-safe-assembly |
||
| 7795 |
assembly {
|
||
| 7796 |
function writeString(pos, w) {
|
||
| 7797 |
let length := 0 |
||
| 7798 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7799 |
mstore(pos, length) |
||
| 7800 |
let shift := sub(256, shl(3, length)) |
||
| 7801 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7802 |
} |
||
| 7803 |
m0 := mload(0x00) |
||
| 7804 |
m1 := mload(0x20) |
||
| 7805 |
m2 := mload(0x40) |
||
| 7806 |
m3 := mload(0x60) |
||
| 7807 |
m4 := mload(0x80) |
||
| 7808 |
m5 := mload(0xa0) |
||
| 7809 |
m6 := mload(0xc0) |
||
| 7810 |
// Selector of `log(bool,string,uint256,bool)`. |
||
| 7811 |
mstore(0x00, 0x6b0e5d53) |
||
| 7812 |
mstore(0x20, p0) |
||
| 7813 |
mstore(0x40, 0x80) |
||
| 7814 |
mstore(0x60, p2) |
||
| 7815 |
mstore(0x80, p3) |
||
| 7816 |
writeString(0xa0, p1) |
||
| 7817 |
} |
||
| 7818 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7819 |
/// @solidity memory-safe-assembly |
||
| 7820 |
assembly {
|
||
| 7821 |
mstore(0x00, m0) |
||
| 7822 |
mstore(0x20, m1) |
||
| 7823 |
mstore(0x40, m2) |
||
| 7824 |
mstore(0x60, m3) |
||
| 7825 |
mstore(0x80, m4) |
||
| 7826 |
mstore(0xa0, m5) |
||
| 7827 |
mstore(0xc0, m6) |
||
| 7828 |
} |
||
| 7829 |
} |
||
| 7830 | |||
| 7831 |
function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 7832 |
bytes32 m0; |
||
| 7833 |
bytes32 m1; |
||
| 7834 |
bytes32 m2; |
||
| 7835 |
bytes32 m3; |
||
| 7836 |
bytes32 m4; |
||
| 7837 |
bytes32 m5; |
||
| 7838 |
bytes32 m6; |
||
| 7839 |
/// @solidity memory-safe-assembly |
||
| 7840 |
assembly {
|
||
| 7841 |
function writeString(pos, w) {
|
||
| 7842 |
let length := 0 |
||
| 7843 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7844 |
mstore(pos, length) |
||
| 7845 |
let shift := sub(256, shl(3, length)) |
||
| 7846 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7847 |
} |
||
| 7848 |
m0 := mload(0x00) |
||
| 7849 |
m1 := mload(0x20) |
||
| 7850 |
m2 := mload(0x40) |
||
| 7851 |
m3 := mload(0x60) |
||
| 7852 |
m4 := mload(0x80) |
||
| 7853 |
m5 := mload(0xa0) |
||
| 7854 |
m6 := mload(0xc0) |
||
| 7855 |
// Selector of `log(bool,string,uint256,uint256)`. |
||
| 7856 |
mstore(0x00, 0x28863fcb) |
||
| 7857 |
mstore(0x20, p0) |
||
| 7858 |
mstore(0x40, 0x80) |
||
| 7859 |
mstore(0x60, p2) |
||
| 7860 |
mstore(0x80, p3) |
||
| 7861 |
writeString(0xa0, p1) |
||
| 7862 |
} |
||
| 7863 |
_sendLogPayload(0x1c, 0xc4); |
||
| 7864 |
/// @solidity memory-safe-assembly |
||
| 7865 |
assembly {
|
||
| 7866 |
mstore(0x00, m0) |
||
| 7867 |
mstore(0x20, m1) |
||
| 7868 |
mstore(0x40, m2) |
||
| 7869 |
mstore(0x60, m3) |
||
| 7870 |
mstore(0x80, m4) |
||
| 7871 |
mstore(0xa0, m5) |
||
| 7872 |
mstore(0xc0, m6) |
||
| 7873 |
} |
||
| 7874 |
} |
||
| 7875 | |||
| 7876 |
function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 7877 |
bytes32 m0; |
||
| 7878 |
bytes32 m1; |
||
| 7879 |
bytes32 m2; |
||
| 7880 |
bytes32 m3; |
||
| 7881 |
bytes32 m4; |
||
| 7882 |
bytes32 m5; |
||
| 7883 |
bytes32 m6; |
||
| 7884 |
bytes32 m7; |
||
| 7885 |
bytes32 m8; |
||
| 7886 |
/// @solidity memory-safe-assembly |
||
| 7887 |
assembly {
|
||
| 7888 |
function writeString(pos, w) {
|
||
| 7889 |
let length := 0 |
||
| 7890 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7891 |
mstore(pos, length) |
||
| 7892 |
let shift := sub(256, shl(3, length)) |
||
| 7893 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7894 |
} |
||
| 7895 |
m0 := mload(0x00) |
||
| 7896 |
m1 := mload(0x20) |
||
| 7897 |
m2 := mload(0x40) |
||
| 7898 |
m3 := mload(0x60) |
||
| 7899 |
m4 := mload(0x80) |
||
| 7900 |
m5 := mload(0xa0) |
||
| 7901 |
m6 := mload(0xc0) |
||
| 7902 |
m7 := mload(0xe0) |
||
| 7903 |
m8 := mload(0x100) |
||
| 7904 |
// Selector of `log(bool,string,uint256,string)`. |
||
| 7905 |
mstore(0x00, 0x1ad96de6) |
||
| 7906 |
mstore(0x20, p0) |
||
| 7907 |
mstore(0x40, 0x80) |
||
| 7908 |
mstore(0x60, p2) |
||
| 7909 |
mstore(0x80, 0xc0) |
||
| 7910 |
writeString(0xa0, p1) |
||
| 7911 |
writeString(0xe0, p3) |
||
| 7912 |
} |
||
| 7913 |
_sendLogPayload(0x1c, 0x104); |
||
| 7914 |
/// @solidity memory-safe-assembly |
||
| 7915 |
assembly {
|
||
| 7916 |
mstore(0x00, m0) |
||
| 7917 |
mstore(0x20, m1) |
||
| 7918 |
mstore(0x40, m2) |
||
| 7919 |
mstore(0x60, m3) |
||
| 7920 |
mstore(0x80, m4) |
||
| 7921 |
mstore(0xa0, m5) |
||
| 7922 |
mstore(0xc0, m6) |
||
| 7923 |
mstore(0xe0, m7) |
||
| 7924 |
mstore(0x100, m8) |
||
| 7925 |
} |
||
| 7926 |
} |
||
| 7927 | |||
| 7928 |
function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure {
|
||
| 7929 |
bytes32 m0; |
||
| 7930 |
bytes32 m1; |
||
| 7931 |
bytes32 m2; |
||
| 7932 |
bytes32 m3; |
||
| 7933 |
bytes32 m4; |
||
| 7934 |
bytes32 m5; |
||
| 7935 |
bytes32 m6; |
||
| 7936 |
bytes32 m7; |
||
| 7937 |
bytes32 m8; |
||
| 7938 |
/// @solidity memory-safe-assembly |
||
| 7939 |
assembly {
|
||
| 7940 |
function writeString(pos, w) {
|
||
| 7941 |
let length := 0 |
||
| 7942 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7943 |
mstore(pos, length) |
||
| 7944 |
let shift := sub(256, shl(3, length)) |
||
| 7945 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7946 |
} |
||
| 7947 |
m0 := mload(0x00) |
||
| 7948 |
m1 := mload(0x20) |
||
| 7949 |
m2 := mload(0x40) |
||
| 7950 |
m3 := mload(0x60) |
||
| 7951 |
m4 := mload(0x80) |
||
| 7952 |
m5 := mload(0xa0) |
||
| 7953 |
m6 := mload(0xc0) |
||
| 7954 |
m7 := mload(0xe0) |
||
| 7955 |
m8 := mload(0x100) |
||
| 7956 |
// Selector of `log(bool,string,string,address)`. |
||
| 7957 |
mstore(0x00, 0x97d394d8) |
||
| 7958 |
mstore(0x20, p0) |
||
| 7959 |
mstore(0x40, 0x80) |
||
| 7960 |
mstore(0x60, 0xc0) |
||
| 7961 |
mstore(0x80, p3) |
||
| 7962 |
writeString(0xa0, p1) |
||
| 7963 |
writeString(0xe0, p2) |
||
| 7964 |
} |
||
| 7965 |
_sendLogPayload(0x1c, 0x104); |
||
| 7966 |
/// @solidity memory-safe-assembly |
||
| 7967 |
assembly {
|
||
| 7968 |
mstore(0x00, m0) |
||
| 7969 |
mstore(0x20, m1) |
||
| 7970 |
mstore(0x40, m2) |
||
| 7971 |
mstore(0x60, m3) |
||
| 7972 |
mstore(0x80, m4) |
||
| 7973 |
mstore(0xa0, m5) |
||
| 7974 |
mstore(0xc0, m6) |
||
| 7975 |
mstore(0xe0, m7) |
||
| 7976 |
mstore(0x100, m8) |
||
| 7977 |
} |
||
| 7978 |
} |
||
| 7979 | |||
| 7980 |
function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
|
||
| 7981 |
bytes32 m0; |
||
| 7982 |
bytes32 m1; |
||
| 7983 |
bytes32 m2; |
||
| 7984 |
bytes32 m3; |
||
| 7985 |
bytes32 m4; |
||
| 7986 |
bytes32 m5; |
||
| 7987 |
bytes32 m6; |
||
| 7988 |
bytes32 m7; |
||
| 7989 |
bytes32 m8; |
||
| 7990 |
/// @solidity memory-safe-assembly |
||
| 7991 |
assembly {
|
||
| 7992 |
function writeString(pos, w) {
|
||
| 7993 |
let length := 0 |
||
| 7994 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 7995 |
mstore(pos, length) |
||
| 7996 |
let shift := sub(256, shl(3, length)) |
||
| 7997 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 7998 |
} |
||
| 7999 |
m0 := mload(0x00) |
||
| 8000 |
m1 := mload(0x20) |
||
| 8001 |
m2 := mload(0x40) |
||
| 8002 |
m3 := mload(0x60) |
||
| 8003 |
m4 := mload(0x80) |
||
| 8004 |
m5 := mload(0xa0) |
||
| 8005 |
m6 := mload(0xc0) |
||
| 8006 |
m7 := mload(0xe0) |
||
| 8007 |
m8 := mload(0x100) |
||
| 8008 |
// Selector of `log(bool,string,string,bool)`. |
||
| 8009 |
mstore(0x00, 0x1e4b87e5) |
||
| 8010 |
mstore(0x20, p0) |
||
| 8011 |
mstore(0x40, 0x80) |
||
| 8012 |
mstore(0x60, 0xc0) |
||
| 8013 |
mstore(0x80, p3) |
||
| 8014 |
writeString(0xa0, p1) |
||
| 8015 |
writeString(0xe0, p2) |
||
| 8016 |
} |
||
| 8017 |
_sendLogPayload(0x1c, 0x104); |
||
| 8018 |
/// @solidity memory-safe-assembly |
||
| 8019 |
assembly {
|
||
| 8020 |
mstore(0x00, m0) |
||
| 8021 |
mstore(0x20, m1) |
||
| 8022 |
mstore(0x40, m2) |
||
| 8023 |
mstore(0x60, m3) |
||
| 8024 |
mstore(0x80, m4) |
||
| 8025 |
mstore(0xa0, m5) |
||
| 8026 |
mstore(0xc0, m6) |
||
| 8027 |
mstore(0xe0, m7) |
||
| 8028 |
mstore(0x100, m8) |
||
| 8029 |
} |
||
| 8030 |
} |
||
| 8031 | |||
| 8032 |
function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 8033 |
bytes32 m0; |
||
| 8034 |
bytes32 m1; |
||
| 8035 |
bytes32 m2; |
||
| 8036 |
bytes32 m3; |
||
| 8037 |
bytes32 m4; |
||
| 8038 |
bytes32 m5; |
||
| 8039 |
bytes32 m6; |
||
| 8040 |
bytes32 m7; |
||
| 8041 |
bytes32 m8; |
||
| 8042 |
/// @solidity memory-safe-assembly |
||
| 8043 |
assembly {
|
||
| 8044 |
function writeString(pos, w) {
|
||
| 8045 |
let length := 0 |
||
| 8046 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8047 |
mstore(pos, length) |
||
| 8048 |
let shift := sub(256, shl(3, length)) |
||
| 8049 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8050 |
} |
||
| 8051 |
m0 := mload(0x00) |
||
| 8052 |
m1 := mload(0x20) |
||
| 8053 |
m2 := mload(0x40) |
||
| 8054 |
m3 := mload(0x60) |
||
| 8055 |
m4 := mload(0x80) |
||
| 8056 |
m5 := mload(0xa0) |
||
| 8057 |
m6 := mload(0xc0) |
||
| 8058 |
m7 := mload(0xe0) |
||
| 8059 |
m8 := mload(0x100) |
||
| 8060 |
// Selector of `log(bool,string,string,uint256)`. |
||
| 8061 |
mstore(0x00, 0x7be0c3eb) |
||
| 8062 |
mstore(0x20, p0) |
||
| 8063 |
mstore(0x40, 0x80) |
||
| 8064 |
mstore(0x60, 0xc0) |
||
| 8065 |
mstore(0x80, p3) |
||
| 8066 |
writeString(0xa0, p1) |
||
| 8067 |
writeString(0xe0, p2) |
||
| 8068 |
} |
||
| 8069 |
_sendLogPayload(0x1c, 0x104); |
||
| 8070 |
/// @solidity memory-safe-assembly |
||
| 8071 |
assembly {
|
||
| 8072 |
mstore(0x00, m0) |
||
| 8073 |
mstore(0x20, m1) |
||
| 8074 |
mstore(0x40, m2) |
||
| 8075 |
mstore(0x60, m3) |
||
| 8076 |
mstore(0x80, m4) |
||
| 8077 |
mstore(0xa0, m5) |
||
| 8078 |
mstore(0xc0, m6) |
||
| 8079 |
mstore(0xe0, m7) |
||
| 8080 |
mstore(0x100, m8) |
||
| 8081 |
} |
||
| 8082 |
} |
||
| 8083 | |||
| 8084 |
function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 8085 |
bytes32 m0; |
||
| 8086 |
bytes32 m1; |
||
| 8087 |
bytes32 m2; |
||
| 8088 |
bytes32 m3; |
||
| 8089 |
bytes32 m4; |
||
| 8090 |
bytes32 m5; |
||
| 8091 |
bytes32 m6; |
||
| 8092 |
bytes32 m7; |
||
| 8093 |
bytes32 m8; |
||
| 8094 |
bytes32 m9; |
||
| 8095 |
bytes32 m10; |
||
| 8096 |
/// @solidity memory-safe-assembly |
||
| 8097 |
assembly {
|
||
| 8098 |
function writeString(pos, w) {
|
||
| 8099 |
let length := 0 |
||
| 8100 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8101 |
mstore(pos, length) |
||
| 8102 |
let shift := sub(256, shl(3, length)) |
||
| 8103 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8104 |
} |
||
| 8105 |
m0 := mload(0x00) |
||
| 8106 |
m1 := mload(0x20) |
||
| 8107 |
m2 := mload(0x40) |
||
| 8108 |
m3 := mload(0x60) |
||
| 8109 |
m4 := mload(0x80) |
||
| 8110 |
m5 := mload(0xa0) |
||
| 8111 |
m6 := mload(0xc0) |
||
| 8112 |
m7 := mload(0xe0) |
||
| 8113 |
m8 := mload(0x100) |
||
| 8114 |
m9 := mload(0x120) |
||
| 8115 |
m10 := mload(0x140) |
||
| 8116 |
// Selector of `log(bool,string,string,string)`. |
||
| 8117 |
mstore(0x00, 0x1762e32a) |
||
| 8118 |
mstore(0x20, p0) |
||
| 8119 |
mstore(0x40, 0x80) |
||
| 8120 |
mstore(0x60, 0xc0) |
||
| 8121 |
mstore(0x80, 0x100) |
||
| 8122 |
writeString(0xa0, p1) |
||
| 8123 |
writeString(0xe0, p2) |
||
| 8124 |
writeString(0x120, p3) |
||
| 8125 |
} |
||
| 8126 |
_sendLogPayload(0x1c, 0x144); |
||
| 8127 |
/// @solidity memory-safe-assembly |
||
| 8128 |
assembly {
|
||
| 8129 |
mstore(0x00, m0) |
||
| 8130 |
mstore(0x20, m1) |
||
| 8131 |
mstore(0x40, m2) |
||
| 8132 |
mstore(0x60, m3) |
||
| 8133 |
mstore(0x80, m4) |
||
| 8134 |
mstore(0xa0, m5) |
||
| 8135 |
mstore(0xc0, m6) |
||
| 8136 |
mstore(0xe0, m7) |
||
| 8137 |
mstore(0x100, m8) |
||
| 8138 |
mstore(0x120, m9) |
||
| 8139 |
mstore(0x140, m10) |
||
| 8140 |
} |
||
| 8141 |
} |
||
| 8142 | |||
| 8143 |
function log(uint256 p0, address p1, address p2, address p3) internal pure {
|
||
| 8144 |
bytes32 m0; |
||
| 8145 |
bytes32 m1; |
||
| 8146 |
bytes32 m2; |
||
| 8147 |
bytes32 m3; |
||
| 8148 |
bytes32 m4; |
||
| 8149 |
/// @solidity memory-safe-assembly |
||
| 8150 |
assembly {
|
||
| 8151 |
m0 := mload(0x00) |
||
| 8152 |
m1 := mload(0x20) |
||
| 8153 |
m2 := mload(0x40) |
||
| 8154 |
m3 := mload(0x60) |
||
| 8155 |
m4 := mload(0x80) |
||
| 8156 |
// Selector of `log(uint256,address,address,address)`. |
||
| 8157 |
mstore(0x00, 0x2488b414) |
||
| 8158 |
mstore(0x20, p0) |
||
| 8159 |
mstore(0x40, p1) |
||
| 8160 |
mstore(0x60, p2) |
||
| 8161 |
mstore(0x80, p3) |
||
| 8162 |
} |
||
| 8163 |
_sendLogPayload(0x1c, 0x84); |
||
| 8164 |
/// @solidity memory-safe-assembly |
||
| 8165 |
assembly {
|
||
| 8166 |
mstore(0x00, m0) |
||
| 8167 |
mstore(0x20, m1) |
||
| 8168 |
mstore(0x40, m2) |
||
| 8169 |
mstore(0x60, m3) |
||
| 8170 |
mstore(0x80, m4) |
||
| 8171 |
} |
||
| 8172 |
} |
||
| 8173 | |||
| 8174 |
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
|
||
| 8175 |
bytes32 m0; |
||
| 8176 |
bytes32 m1; |
||
| 8177 |
bytes32 m2; |
||
| 8178 |
bytes32 m3; |
||
| 8179 |
bytes32 m4; |
||
| 8180 |
/// @solidity memory-safe-assembly |
||
| 8181 |
assembly {
|
||
| 8182 |
m0 := mload(0x00) |
||
| 8183 |
m1 := mload(0x20) |
||
| 8184 |
m2 := mload(0x40) |
||
| 8185 |
m3 := mload(0x60) |
||
| 8186 |
m4 := mload(0x80) |
||
| 8187 |
// Selector of `log(uint256,address,address,bool)`. |
||
| 8188 |
mstore(0x00, 0x091ffaf5) |
||
| 8189 |
mstore(0x20, p0) |
||
| 8190 |
mstore(0x40, p1) |
||
| 8191 |
mstore(0x60, p2) |
||
| 8192 |
mstore(0x80, p3) |
||
| 8193 |
} |
||
| 8194 |
_sendLogPayload(0x1c, 0x84); |
||
| 8195 |
/// @solidity memory-safe-assembly |
||
| 8196 |
assembly {
|
||
| 8197 |
mstore(0x00, m0) |
||
| 8198 |
mstore(0x20, m1) |
||
| 8199 |
mstore(0x40, m2) |
||
| 8200 |
mstore(0x60, m3) |
||
| 8201 |
mstore(0x80, m4) |
||
| 8202 |
} |
||
| 8203 |
} |
||
| 8204 | |||
| 8205 |
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
|
||
| 8206 |
bytes32 m0; |
||
| 8207 |
bytes32 m1; |
||
| 8208 |
bytes32 m2; |
||
| 8209 |
bytes32 m3; |
||
| 8210 |
bytes32 m4; |
||
| 8211 |
/// @solidity memory-safe-assembly |
||
| 8212 |
assembly {
|
||
| 8213 |
m0 := mload(0x00) |
||
| 8214 |
m1 := mload(0x20) |
||
| 8215 |
m2 := mload(0x40) |
||
| 8216 |
m3 := mload(0x60) |
||
| 8217 |
m4 := mload(0x80) |
||
| 8218 |
// Selector of `log(uint256,address,address,uint256)`. |
||
| 8219 |
mstore(0x00, 0x736efbb6) |
||
| 8220 |
mstore(0x20, p0) |
||
| 8221 |
mstore(0x40, p1) |
||
| 8222 |
mstore(0x60, p2) |
||
| 8223 |
mstore(0x80, p3) |
||
| 8224 |
} |
||
| 8225 |
_sendLogPayload(0x1c, 0x84); |
||
| 8226 |
/// @solidity memory-safe-assembly |
||
| 8227 |
assembly {
|
||
| 8228 |
mstore(0x00, m0) |
||
| 8229 |
mstore(0x20, m1) |
||
| 8230 |
mstore(0x40, m2) |
||
| 8231 |
mstore(0x60, m3) |
||
| 8232 |
mstore(0x80, m4) |
||
| 8233 |
} |
||
| 8234 |
} |
||
| 8235 | |||
| 8236 |
function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure {
|
||
| 8237 |
bytes32 m0; |
||
| 8238 |
bytes32 m1; |
||
| 8239 |
bytes32 m2; |
||
| 8240 |
bytes32 m3; |
||
| 8241 |
bytes32 m4; |
||
| 8242 |
bytes32 m5; |
||
| 8243 |
bytes32 m6; |
||
| 8244 |
/// @solidity memory-safe-assembly |
||
| 8245 |
assembly {
|
||
| 8246 |
function writeString(pos, w) {
|
||
| 8247 |
let length := 0 |
||
| 8248 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8249 |
mstore(pos, length) |
||
| 8250 |
let shift := sub(256, shl(3, length)) |
||
| 8251 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8252 |
} |
||
| 8253 |
m0 := mload(0x00) |
||
| 8254 |
m1 := mload(0x20) |
||
| 8255 |
m2 := mload(0x40) |
||
| 8256 |
m3 := mload(0x60) |
||
| 8257 |
m4 := mload(0x80) |
||
| 8258 |
m5 := mload(0xa0) |
||
| 8259 |
m6 := mload(0xc0) |
||
| 8260 |
// Selector of `log(uint256,address,address,string)`. |
||
| 8261 |
mstore(0x00, 0x031c6f73) |
||
| 8262 |
mstore(0x20, p0) |
||
| 8263 |
mstore(0x40, p1) |
||
| 8264 |
mstore(0x60, p2) |
||
| 8265 |
mstore(0x80, 0x80) |
||
| 8266 |
writeString(0xa0, p3) |
||
| 8267 |
} |
||
| 8268 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8269 |
/// @solidity memory-safe-assembly |
||
| 8270 |
assembly {
|
||
| 8271 |
mstore(0x00, m0) |
||
| 8272 |
mstore(0x20, m1) |
||
| 8273 |
mstore(0x40, m2) |
||
| 8274 |
mstore(0x60, m3) |
||
| 8275 |
mstore(0x80, m4) |
||
| 8276 |
mstore(0xa0, m5) |
||
| 8277 |
mstore(0xc0, m6) |
||
| 8278 |
} |
||
| 8279 |
} |
||
| 8280 | |||
| 8281 |
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
|
||
| 8282 |
bytes32 m0; |
||
| 8283 |
bytes32 m1; |
||
| 8284 |
bytes32 m2; |
||
| 8285 |
bytes32 m3; |
||
| 8286 |
bytes32 m4; |
||
| 8287 |
/// @solidity memory-safe-assembly |
||
| 8288 |
assembly {
|
||
| 8289 |
m0 := mload(0x00) |
||
| 8290 |
m1 := mload(0x20) |
||
| 8291 |
m2 := mload(0x40) |
||
| 8292 |
m3 := mload(0x60) |
||
| 8293 |
m4 := mload(0x80) |
||
| 8294 |
// Selector of `log(uint256,address,bool,address)`. |
||
| 8295 |
mstore(0x00, 0xef72c513) |
||
| 8296 |
mstore(0x20, p0) |
||
| 8297 |
mstore(0x40, p1) |
||
| 8298 |
mstore(0x60, p2) |
||
| 8299 |
mstore(0x80, p3) |
||
| 8300 |
} |
||
| 8301 |
_sendLogPayload(0x1c, 0x84); |
||
| 8302 |
/// @solidity memory-safe-assembly |
||
| 8303 |
assembly {
|
||
| 8304 |
mstore(0x00, m0) |
||
| 8305 |
mstore(0x20, m1) |
||
| 8306 |
mstore(0x40, m2) |
||
| 8307 |
mstore(0x60, m3) |
||
| 8308 |
mstore(0x80, m4) |
||
| 8309 |
} |
||
| 8310 |
} |
||
| 8311 | |||
| 8312 |
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
|
||
| 8313 |
bytes32 m0; |
||
| 8314 |
bytes32 m1; |
||
| 8315 |
bytes32 m2; |
||
| 8316 |
bytes32 m3; |
||
| 8317 |
bytes32 m4; |
||
| 8318 |
/// @solidity memory-safe-assembly |
||
| 8319 |
assembly {
|
||
| 8320 |
m0 := mload(0x00) |
||
| 8321 |
m1 := mload(0x20) |
||
| 8322 |
m2 := mload(0x40) |
||
| 8323 |
m3 := mload(0x60) |
||
| 8324 |
m4 := mload(0x80) |
||
| 8325 |
// Selector of `log(uint256,address,bool,bool)`. |
||
| 8326 |
mstore(0x00, 0xe351140f) |
||
| 8327 |
mstore(0x20, p0) |
||
| 8328 |
mstore(0x40, p1) |
||
| 8329 |
mstore(0x60, p2) |
||
| 8330 |
mstore(0x80, p3) |
||
| 8331 |
} |
||
| 8332 |
_sendLogPayload(0x1c, 0x84); |
||
| 8333 |
/// @solidity memory-safe-assembly |
||
| 8334 |
assembly {
|
||
| 8335 |
mstore(0x00, m0) |
||
| 8336 |
mstore(0x20, m1) |
||
| 8337 |
mstore(0x40, m2) |
||
| 8338 |
mstore(0x60, m3) |
||
| 8339 |
mstore(0x80, m4) |
||
| 8340 |
} |
||
| 8341 |
} |
||
| 8342 | |||
| 8343 |
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
|
||
| 8344 |
bytes32 m0; |
||
| 8345 |
bytes32 m1; |
||
| 8346 |
bytes32 m2; |
||
| 8347 |
bytes32 m3; |
||
| 8348 |
bytes32 m4; |
||
| 8349 |
/// @solidity memory-safe-assembly |
||
| 8350 |
assembly {
|
||
| 8351 |
m0 := mload(0x00) |
||
| 8352 |
m1 := mload(0x20) |
||
| 8353 |
m2 := mload(0x40) |
||
| 8354 |
m3 := mload(0x60) |
||
| 8355 |
m4 := mload(0x80) |
||
| 8356 |
// Selector of `log(uint256,address,bool,uint256)`. |
||
| 8357 |
mstore(0x00, 0x5abd992a) |
||
| 8358 |
mstore(0x20, p0) |
||
| 8359 |
mstore(0x40, p1) |
||
| 8360 |
mstore(0x60, p2) |
||
| 8361 |
mstore(0x80, p3) |
||
| 8362 |
} |
||
| 8363 |
_sendLogPayload(0x1c, 0x84); |
||
| 8364 |
/// @solidity memory-safe-assembly |
||
| 8365 |
assembly {
|
||
| 8366 |
mstore(0x00, m0) |
||
| 8367 |
mstore(0x20, m1) |
||
| 8368 |
mstore(0x40, m2) |
||
| 8369 |
mstore(0x60, m3) |
||
| 8370 |
mstore(0x80, m4) |
||
| 8371 |
} |
||
| 8372 |
} |
||
| 8373 | |||
| 8374 |
function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure {
|
||
| 8375 |
bytes32 m0; |
||
| 8376 |
bytes32 m1; |
||
| 8377 |
bytes32 m2; |
||
| 8378 |
bytes32 m3; |
||
| 8379 |
bytes32 m4; |
||
| 8380 |
bytes32 m5; |
||
| 8381 |
bytes32 m6; |
||
| 8382 |
/// @solidity memory-safe-assembly |
||
| 8383 |
assembly {
|
||
| 8384 |
function writeString(pos, w) {
|
||
| 8385 |
let length := 0 |
||
| 8386 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8387 |
mstore(pos, length) |
||
| 8388 |
let shift := sub(256, shl(3, length)) |
||
| 8389 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8390 |
} |
||
| 8391 |
m0 := mload(0x00) |
||
| 8392 |
m1 := mload(0x20) |
||
| 8393 |
m2 := mload(0x40) |
||
| 8394 |
m3 := mload(0x60) |
||
| 8395 |
m4 := mload(0x80) |
||
| 8396 |
m5 := mload(0xa0) |
||
| 8397 |
m6 := mload(0xc0) |
||
| 8398 |
// Selector of `log(uint256,address,bool,string)`. |
||
| 8399 |
mstore(0x00, 0x90fb06aa) |
||
| 8400 |
mstore(0x20, p0) |
||
| 8401 |
mstore(0x40, p1) |
||
| 8402 |
mstore(0x60, p2) |
||
| 8403 |
mstore(0x80, 0x80) |
||
| 8404 |
writeString(0xa0, p3) |
||
| 8405 |
} |
||
| 8406 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8407 |
/// @solidity memory-safe-assembly |
||
| 8408 |
assembly {
|
||
| 8409 |
mstore(0x00, m0) |
||
| 8410 |
mstore(0x20, m1) |
||
| 8411 |
mstore(0x40, m2) |
||
| 8412 |
mstore(0x60, m3) |
||
| 8413 |
mstore(0x80, m4) |
||
| 8414 |
mstore(0xa0, m5) |
||
| 8415 |
mstore(0xc0, m6) |
||
| 8416 |
} |
||
| 8417 |
} |
||
| 8418 | |||
| 8419 |
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
|
||
| 8420 |
bytes32 m0; |
||
| 8421 |
bytes32 m1; |
||
| 8422 |
bytes32 m2; |
||
| 8423 |
bytes32 m3; |
||
| 8424 |
bytes32 m4; |
||
| 8425 |
/// @solidity memory-safe-assembly |
||
| 8426 |
assembly {
|
||
| 8427 |
m0 := mload(0x00) |
||
| 8428 |
m1 := mload(0x20) |
||
| 8429 |
m2 := mload(0x40) |
||
| 8430 |
m3 := mload(0x60) |
||
| 8431 |
m4 := mload(0x80) |
||
| 8432 |
// Selector of `log(uint256,address,uint256,address)`. |
||
| 8433 |
mstore(0x00, 0x15c127b5) |
||
| 8434 |
mstore(0x20, p0) |
||
| 8435 |
mstore(0x40, p1) |
||
| 8436 |
mstore(0x60, p2) |
||
| 8437 |
mstore(0x80, p3) |
||
| 8438 |
} |
||
| 8439 |
_sendLogPayload(0x1c, 0x84); |
||
| 8440 |
/// @solidity memory-safe-assembly |
||
| 8441 |
assembly {
|
||
| 8442 |
mstore(0x00, m0) |
||
| 8443 |
mstore(0x20, m1) |
||
| 8444 |
mstore(0x40, m2) |
||
| 8445 |
mstore(0x60, m3) |
||
| 8446 |
mstore(0x80, m4) |
||
| 8447 |
} |
||
| 8448 |
} |
||
| 8449 | |||
| 8450 |
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
|
||
| 8451 |
bytes32 m0; |
||
| 8452 |
bytes32 m1; |
||
| 8453 |
bytes32 m2; |
||
| 8454 |
bytes32 m3; |
||
| 8455 |
bytes32 m4; |
||
| 8456 |
/// @solidity memory-safe-assembly |
||
| 8457 |
assembly {
|
||
| 8458 |
m0 := mload(0x00) |
||
| 8459 |
m1 := mload(0x20) |
||
| 8460 |
m2 := mload(0x40) |
||
| 8461 |
m3 := mload(0x60) |
||
| 8462 |
m4 := mload(0x80) |
||
| 8463 |
// Selector of `log(uint256,address,uint256,bool)`. |
||
| 8464 |
mstore(0x00, 0x5f743a7c) |
||
| 8465 |
mstore(0x20, p0) |
||
| 8466 |
mstore(0x40, p1) |
||
| 8467 |
mstore(0x60, p2) |
||
| 8468 |
mstore(0x80, p3) |
||
| 8469 |
} |
||
| 8470 |
_sendLogPayload(0x1c, 0x84); |
||
| 8471 |
/// @solidity memory-safe-assembly |
||
| 8472 |
assembly {
|
||
| 8473 |
mstore(0x00, m0) |
||
| 8474 |
mstore(0x20, m1) |
||
| 8475 |
mstore(0x40, m2) |
||
| 8476 |
mstore(0x60, m3) |
||
| 8477 |
mstore(0x80, m4) |
||
| 8478 |
} |
||
| 8479 |
} |
||
| 8480 | |||
| 8481 |
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
|
||
| 8482 |
bytes32 m0; |
||
| 8483 |
bytes32 m1; |
||
| 8484 |
bytes32 m2; |
||
| 8485 |
bytes32 m3; |
||
| 8486 |
bytes32 m4; |
||
| 8487 |
/// @solidity memory-safe-assembly |
||
| 8488 |
assembly {
|
||
| 8489 |
m0 := mload(0x00) |
||
| 8490 |
m1 := mload(0x20) |
||
| 8491 |
m2 := mload(0x40) |
||
| 8492 |
m3 := mload(0x60) |
||
| 8493 |
m4 := mload(0x80) |
||
| 8494 |
// Selector of `log(uint256,address,uint256,uint256)`. |
||
| 8495 |
mstore(0x00, 0x0c9cd9c1) |
||
| 8496 |
mstore(0x20, p0) |
||
| 8497 |
mstore(0x40, p1) |
||
| 8498 |
mstore(0x60, p2) |
||
| 8499 |
mstore(0x80, p3) |
||
| 8500 |
} |
||
| 8501 |
_sendLogPayload(0x1c, 0x84); |
||
| 8502 |
/// @solidity memory-safe-assembly |
||
| 8503 |
assembly {
|
||
| 8504 |
mstore(0x00, m0) |
||
| 8505 |
mstore(0x20, m1) |
||
| 8506 |
mstore(0x40, m2) |
||
| 8507 |
mstore(0x60, m3) |
||
| 8508 |
mstore(0x80, m4) |
||
| 8509 |
} |
||
| 8510 |
} |
||
| 8511 | |||
| 8512 |
function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 8513 |
bytes32 m0; |
||
| 8514 |
bytes32 m1; |
||
| 8515 |
bytes32 m2; |
||
| 8516 |
bytes32 m3; |
||
| 8517 |
bytes32 m4; |
||
| 8518 |
bytes32 m5; |
||
| 8519 |
bytes32 m6; |
||
| 8520 |
/// @solidity memory-safe-assembly |
||
| 8521 |
assembly {
|
||
| 8522 |
function writeString(pos, w) {
|
||
| 8523 |
let length := 0 |
||
| 8524 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8525 |
mstore(pos, length) |
||
| 8526 |
let shift := sub(256, shl(3, length)) |
||
| 8527 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8528 |
} |
||
| 8529 |
m0 := mload(0x00) |
||
| 8530 |
m1 := mload(0x20) |
||
| 8531 |
m2 := mload(0x40) |
||
| 8532 |
m3 := mload(0x60) |
||
| 8533 |
m4 := mload(0x80) |
||
| 8534 |
m5 := mload(0xa0) |
||
| 8535 |
m6 := mload(0xc0) |
||
| 8536 |
// Selector of `log(uint256,address,uint256,string)`. |
||
| 8537 |
mstore(0x00, 0xddb06521) |
||
| 8538 |
mstore(0x20, p0) |
||
| 8539 |
mstore(0x40, p1) |
||
| 8540 |
mstore(0x60, p2) |
||
| 8541 |
mstore(0x80, 0x80) |
||
| 8542 |
writeString(0xa0, p3) |
||
| 8543 |
} |
||
| 8544 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8545 |
/// @solidity memory-safe-assembly |
||
| 8546 |
assembly {
|
||
| 8547 |
mstore(0x00, m0) |
||
| 8548 |
mstore(0x20, m1) |
||
| 8549 |
mstore(0x40, m2) |
||
| 8550 |
mstore(0x60, m3) |
||
| 8551 |
mstore(0x80, m4) |
||
| 8552 |
mstore(0xa0, m5) |
||
| 8553 |
mstore(0xc0, m6) |
||
| 8554 |
} |
||
| 8555 |
} |
||
| 8556 | |||
| 8557 |
function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure {
|
||
| 8558 |
bytes32 m0; |
||
| 8559 |
bytes32 m1; |
||
| 8560 |
bytes32 m2; |
||
| 8561 |
bytes32 m3; |
||
| 8562 |
bytes32 m4; |
||
| 8563 |
bytes32 m5; |
||
| 8564 |
bytes32 m6; |
||
| 8565 |
/// @solidity memory-safe-assembly |
||
| 8566 |
assembly {
|
||
| 8567 |
function writeString(pos, w) {
|
||
| 8568 |
let length := 0 |
||
| 8569 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8570 |
mstore(pos, length) |
||
| 8571 |
let shift := sub(256, shl(3, length)) |
||
| 8572 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8573 |
} |
||
| 8574 |
m0 := mload(0x00) |
||
| 8575 |
m1 := mload(0x20) |
||
| 8576 |
m2 := mload(0x40) |
||
| 8577 |
m3 := mload(0x60) |
||
| 8578 |
m4 := mload(0x80) |
||
| 8579 |
m5 := mload(0xa0) |
||
| 8580 |
m6 := mload(0xc0) |
||
| 8581 |
// Selector of `log(uint256,address,string,address)`. |
||
| 8582 |
mstore(0x00, 0x9cba8fff) |
||
| 8583 |
mstore(0x20, p0) |
||
| 8584 |
mstore(0x40, p1) |
||
| 8585 |
mstore(0x60, 0x80) |
||
| 8586 |
mstore(0x80, p3) |
||
| 8587 |
writeString(0xa0, p2) |
||
| 8588 |
} |
||
| 8589 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8590 |
/// @solidity memory-safe-assembly |
||
| 8591 |
assembly {
|
||
| 8592 |
mstore(0x00, m0) |
||
| 8593 |
mstore(0x20, m1) |
||
| 8594 |
mstore(0x40, m2) |
||
| 8595 |
mstore(0x60, m3) |
||
| 8596 |
mstore(0x80, m4) |
||
| 8597 |
mstore(0xa0, m5) |
||
| 8598 |
mstore(0xc0, m6) |
||
| 8599 |
} |
||
| 8600 |
} |
||
| 8601 | |||
| 8602 |
function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure {
|
||
| 8603 |
bytes32 m0; |
||
| 8604 |
bytes32 m1; |
||
| 8605 |
bytes32 m2; |
||
| 8606 |
bytes32 m3; |
||
| 8607 |
bytes32 m4; |
||
| 8608 |
bytes32 m5; |
||
| 8609 |
bytes32 m6; |
||
| 8610 |
/// @solidity memory-safe-assembly |
||
| 8611 |
assembly {
|
||
| 8612 |
function writeString(pos, w) {
|
||
| 8613 |
let length := 0 |
||
| 8614 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8615 |
mstore(pos, length) |
||
| 8616 |
let shift := sub(256, shl(3, length)) |
||
| 8617 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8618 |
} |
||
| 8619 |
m0 := mload(0x00) |
||
| 8620 |
m1 := mload(0x20) |
||
| 8621 |
m2 := mload(0x40) |
||
| 8622 |
m3 := mload(0x60) |
||
| 8623 |
m4 := mload(0x80) |
||
| 8624 |
m5 := mload(0xa0) |
||
| 8625 |
m6 := mload(0xc0) |
||
| 8626 |
// Selector of `log(uint256,address,string,bool)`. |
||
| 8627 |
mstore(0x00, 0xcc32ab07) |
||
| 8628 |
mstore(0x20, p0) |
||
| 8629 |
mstore(0x40, p1) |
||
| 8630 |
mstore(0x60, 0x80) |
||
| 8631 |
mstore(0x80, p3) |
||
| 8632 |
writeString(0xa0, p2) |
||
| 8633 |
} |
||
| 8634 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8635 |
/// @solidity memory-safe-assembly |
||
| 8636 |
assembly {
|
||
| 8637 |
mstore(0x00, m0) |
||
| 8638 |
mstore(0x20, m1) |
||
| 8639 |
mstore(0x40, m2) |
||
| 8640 |
mstore(0x60, m3) |
||
| 8641 |
mstore(0x80, m4) |
||
| 8642 |
mstore(0xa0, m5) |
||
| 8643 |
mstore(0xc0, m6) |
||
| 8644 |
} |
||
| 8645 |
} |
||
| 8646 | |||
| 8647 |
function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 8648 |
bytes32 m0; |
||
| 8649 |
bytes32 m1; |
||
| 8650 |
bytes32 m2; |
||
| 8651 |
bytes32 m3; |
||
| 8652 |
bytes32 m4; |
||
| 8653 |
bytes32 m5; |
||
| 8654 |
bytes32 m6; |
||
| 8655 |
/// @solidity memory-safe-assembly |
||
| 8656 |
assembly {
|
||
| 8657 |
function writeString(pos, w) {
|
||
| 8658 |
let length := 0 |
||
| 8659 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8660 |
mstore(pos, length) |
||
| 8661 |
let shift := sub(256, shl(3, length)) |
||
| 8662 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8663 |
} |
||
| 8664 |
m0 := mload(0x00) |
||
| 8665 |
m1 := mload(0x20) |
||
| 8666 |
m2 := mload(0x40) |
||
| 8667 |
m3 := mload(0x60) |
||
| 8668 |
m4 := mload(0x80) |
||
| 8669 |
m5 := mload(0xa0) |
||
| 8670 |
m6 := mload(0xc0) |
||
| 8671 |
// Selector of `log(uint256,address,string,uint256)`. |
||
| 8672 |
mstore(0x00, 0x46826b5d) |
||
| 8673 |
mstore(0x20, p0) |
||
| 8674 |
mstore(0x40, p1) |
||
| 8675 |
mstore(0x60, 0x80) |
||
| 8676 |
mstore(0x80, p3) |
||
| 8677 |
writeString(0xa0, p2) |
||
| 8678 |
} |
||
| 8679 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8680 |
/// @solidity memory-safe-assembly |
||
| 8681 |
assembly {
|
||
| 8682 |
mstore(0x00, m0) |
||
| 8683 |
mstore(0x20, m1) |
||
| 8684 |
mstore(0x40, m2) |
||
| 8685 |
mstore(0x60, m3) |
||
| 8686 |
mstore(0x80, m4) |
||
| 8687 |
mstore(0xa0, m5) |
||
| 8688 |
mstore(0xc0, m6) |
||
| 8689 |
} |
||
| 8690 |
} |
||
| 8691 | |||
| 8692 |
function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 8693 |
bytes32 m0; |
||
| 8694 |
bytes32 m1; |
||
| 8695 |
bytes32 m2; |
||
| 8696 |
bytes32 m3; |
||
| 8697 |
bytes32 m4; |
||
| 8698 |
bytes32 m5; |
||
| 8699 |
bytes32 m6; |
||
| 8700 |
bytes32 m7; |
||
| 8701 |
bytes32 m8; |
||
| 8702 |
/// @solidity memory-safe-assembly |
||
| 8703 |
assembly {
|
||
| 8704 |
function writeString(pos, w) {
|
||
| 8705 |
let length := 0 |
||
| 8706 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8707 |
mstore(pos, length) |
||
| 8708 |
let shift := sub(256, shl(3, length)) |
||
| 8709 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8710 |
} |
||
| 8711 |
m0 := mload(0x00) |
||
| 8712 |
m1 := mload(0x20) |
||
| 8713 |
m2 := mload(0x40) |
||
| 8714 |
m3 := mload(0x60) |
||
| 8715 |
m4 := mload(0x80) |
||
| 8716 |
m5 := mload(0xa0) |
||
| 8717 |
m6 := mload(0xc0) |
||
| 8718 |
m7 := mload(0xe0) |
||
| 8719 |
m8 := mload(0x100) |
||
| 8720 |
// Selector of `log(uint256,address,string,string)`. |
||
| 8721 |
mstore(0x00, 0x3e128ca3) |
||
| 8722 |
mstore(0x20, p0) |
||
| 8723 |
mstore(0x40, p1) |
||
| 8724 |
mstore(0x60, 0x80) |
||
| 8725 |
mstore(0x80, 0xc0) |
||
| 8726 |
writeString(0xa0, p2) |
||
| 8727 |
writeString(0xe0, p3) |
||
| 8728 |
} |
||
| 8729 |
_sendLogPayload(0x1c, 0x104); |
||
| 8730 |
/// @solidity memory-safe-assembly |
||
| 8731 |
assembly {
|
||
| 8732 |
mstore(0x00, m0) |
||
| 8733 |
mstore(0x20, m1) |
||
| 8734 |
mstore(0x40, m2) |
||
| 8735 |
mstore(0x60, m3) |
||
| 8736 |
mstore(0x80, m4) |
||
| 8737 |
mstore(0xa0, m5) |
||
| 8738 |
mstore(0xc0, m6) |
||
| 8739 |
mstore(0xe0, m7) |
||
| 8740 |
mstore(0x100, m8) |
||
| 8741 |
} |
||
| 8742 |
} |
||
| 8743 | |||
| 8744 |
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
|
||
| 8745 |
bytes32 m0; |
||
| 8746 |
bytes32 m1; |
||
| 8747 |
bytes32 m2; |
||
| 8748 |
bytes32 m3; |
||
| 8749 |
bytes32 m4; |
||
| 8750 |
/// @solidity memory-safe-assembly |
||
| 8751 |
assembly {
|
||
| 8752 |
m0 := mload(0x00) |
||
| 8753 |
m1 := mload(0x20) |
||
| 8754 |
m2 := mload(0x40) |
||
| 8755 |
m3 := mload(0x60) |
||
| 8756 |
m4 := mload(0x80) |
||
| 8757 |
// Selector of `log(uint256,bool,address,address)`. |
||
| 8758 |
mstore(0x00, 0xa1ef4cbb) |
||
| 8759 |
mstore(0x20, p0) |
||
| 8760 |
mstore(0x40, p1) |
||
| 8761 |
mstore(0x60, p2) |
||
| 8762 |
mstore(0x80, p3) |
||
| 8763 |
} |
||
| 8764 |
_sendLogPayload(0x1c, 0x84); |
||
| 8765 |
/// @solidity memory-safe-assembly |
||
| 8766 |
assembly {
|
||
| 8767 |
mstore(0x00, m0) |
||
| 8768 |
mstore(0x20, m1) |
||
| 8769 |
mstore(0x40, m2) |
||
| 8770 |
mstore(0x60, m3) |
||
| 8771 |
mstore(0x80, m4) |
||
| 8772 |
} |
||
| 8773 |
} |
||
| 8774 | |||
| 8775 |
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
|
||
| 8776 |
bytes32 m0; |
||
| 8777 |
bytes32 m1; |
||
| 8778 |
bytes32 m2; |
||
| 8779 |
bytes32 m3; |
||
| 8780 |
bytes32 m4; |
||
| 8781 |
/// @solidity memory-safe-assembly |
||
| 8782 |
assembly {
|
||
| 8783 |
m0 := mload(0x00) |
||
| 8784 |
m1 := mload(0x20) |
||
| 8785 |
m2 := mload(0x40) |
||
| 8786 |
m3 := mload(0x60) |
||
| 8787 |
m4 := mload(0x80) |
||
| 8788 |
// Selector of `log(uint256,bool,address,bool)`. |
||
| 8789 |
mstore(0x00, 0x454d54a5) |
||
| 8790 |
mstore(0x20, p0) |
||
| 8791 |
mstore(0x40, p1) |
||
| 8792 |
mstore(0x60, p2) |
||
| 8793 |
mstore(0x80, p3) |
||
| 8794 |
} |
||
| 8795 |
_sendLogPayload(0x1c, 0x84); |
||
| 8796 |
/// @solidity memory-safe-assembly |
||
| 8797 |
assembly {
|
||
| 8798 |
mstore(0x00, m0) |
||
| 8799 |
mstore(0x20, m1) |
||
| 8800 |
mstore(0x40, m2) |
||
| 8801 |
mstore(0x60, m3) |
||
| 8802 |
mstore(0x80, m4) |
||
| 8803 |
} |
||
| 8804 |
} |
||
| 8805 | |||
| 8806 |
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
|
||
| 8807 |
bytes32 m0; |
||
| 8808 |
bytes32 m1; |
||
| 8809 |
bytes32 m2; |
||
| 8810 |
bytes32 m3; |
||
| 8811 |
bytes32 m4; |
||
| 8812 |
/// @solidity memory-safe-assembly |
||
| 8813 |
assembly {
|
||
| 8814 |
m0 := mload(0x00) |
||
| 8815 |
m1 := mload(0x20) |
||
| 8816 |
m2 := mload(0x40) |
||
| 8817 |
m3 := mload(0x60) |
||
| 8818 |
m4 := mload(0x80) |
||
| 8819 |
// Selector of `log(uint256,bool,address,uint256)`. |
||
| 8820 |
mstore(0x00, 0x078287f5) |
||
| 8821 |
mstore(0x20, p0) |
||
| 8822 |
mstore(0x40, p1) |
||
| 8823 |
mstore(0x60, p2) |
||
| 8824 |
mstore(0x80, p3) |
||
| 8825 |
} |
||
| 8826 |
_sendLogPayload(0x1c, 0x84); |
||
| 8827 |
/// @solidity memory-safe-assembly |
||
| 8828 |
assembly {
|
||
| 8829 |
mstore(0x00, m0) |
||
| 8830 |
mstore(0x20, m1) |
||
| 8831 |
mstore(0x40, m2) |
||
| 8832 |
mstore(0x60, m3) |
||
| 8833 |
mstore(0x80, m4) |
||
| 8834 |
} |
||
| 8835 |
} |
||
| 8836 | |||
| 8837 |
function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure {
|
||
| 8838 |
bytes32 m0; |
||
| 8839 |
bytes32 m1; |
||
| 8840 |
bytes32 m2; |
||
| 8841 |
bytes32 m3; |
||
| 8842 |
bytes32 m4; |
||
| 8843 |
bytes32 m5; |
||
| 8844 |
bytes32 m6; |
||
| 8845 |
/// @solidity memory-safe-assembly |
||
| 8846 |
assembly {
|
||
| 8847 |
function writeString(pos, w) {
|
||
| 8848 |
let length := 0 |
||
| 8849 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8850 |
mstore(pos, length) |
||
| 8851 |
let shift := sub(256, shl(3, length)) |
||
| 8852 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8853 |
} |
||
| 8854 |
m0 := mload(0x00) |
||
| 8855 |
m1 := mload(0x20) |
||
| 8856 |
m2 := mload(0x40) |
||
| 8857 |
m3 := mload(0x60) |
||
| 8858 |
m4 := mload(0x80) |
||
| 8859 |
m5 := mload(0xa0) |
||
| 8860 |
m6 := mload(0xc0) |
||
| 8861 |
// Selector of `log(uint256,bool,address,string)`. |
||
| 8862 |
mstore(0x00, 0xade052c7) |
||
| 8863 |
mstore(0x20, p0) |
||
| 8864 |
mstore(0x40, p1) |
||
| 8865 |
mstore(0x60, p2) |
||
| 8866 |
mstore(0x80, 0x80) |
||
| 8867 |
writeString(0xa0, p3) |
||
| 8868 |
} |
||
| 8869 |
_sendLogPayload(0x1c, 0xc4); |
||
| 8870 |
/// @solidity memory-safe-assembly |
||
| 8871 |
assembly {
|
||
| 8872 |
mstore(0x00, m0) |
||
| 8873 |
mstore(0x20, m1) |
||
| 8874 |
mstore(0x40, m2) |
||
| 8875 |
mstore(0x60, m3) |
||
| 8876 |
mstore(0x80, m4) |
||
| 8877 |
mstore(0xa0, m5) |
||
| 8878 |
mstore(0xc0, m6) |
||
| 8879 |
} |
||
| 8880 |
} |
||
| 8881 | |||
| 8882 |
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
|
||
| 8883 |
bytes32 m0; |
||
| 8884 |
bytes32 m1; |
||
| 8885 |
bytes32 m2; |
||
| 8886 |
bytes32 m3; |
||
| 8887 |
bytes32 m4; |
||
| 8888 |
/// @solidity memory-safe-assembly |
||
| 8889 |
assembly {
|
||
| 8890 |
m0 := mload(0x00) |
||
| 8891 |
m1 := mload(0x20) |
||
| 8892 |
m2 := mload(0x40) |
||
| 8893 |
m3 := mload(0x60) |
||
| 8894 |
m4 := mload(0x80) |
||
| 8895 |
// Selector of `log(uint256,bool,bool,address)`. |
||
| 8896 |
mstore(0x00, 0x69640b59) |
||
| 8897 |
mstore(0x20, p0) |
||
| 8898 |
mstore(0x40, p1) |
||
| 8899 |
mstore(0x60, p2) |
||
| 8900 |
mstore(0x80, p3) |
||
| 8901 |
} |
||
| 8902 |
_sendLogPayload(0x1c, 0x84); |
||
| 8903 |
/// @solidity memory-safe-assembly |
||
| 8904 |
assembly {
|
||
| 8905 |
mstore(0x00, m0) |
||
| 8906 |
mstore(0x20, m1) |
||
| 8907 |
mstore(0x40, m2) |
||
| 8908 |
mstore(0x60, m3) |
||
| 8909 |
mstore(0x80, m4) |
||
| 8910 |
} |
||
| 8911 |
} |
||
| 8912 | |||
| 8913 |
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 8914 |
bytes32 m0; |
||
| 8915 |
bytes32 m1; |
||
| 8916 |
bytes32 m2; |
||
| 8917 |
bytes32 m3; |
||
| 8918 |
bytes32 m4; |
||
| 8919 |
/// @solidity memory-safe-assembly |
||
| 8920 |
assembly {
|
||
| 8921 |
m0 := mload(0x00) |
||
| 8922 |
m1 := mload(0x20) |
||
| 8923 |
m2 := mload(0x40) |
||
| 8924 |
m3 := mload(0x60) |
||
| 8925 |
m4 := mload(0x80) |
||
| 8926 |
// Selector of `log(uint256,bool,bool,bool)`. |
||
| 8927 |
mstore(0x00, 0xb6f577a1) |
||
| 8928 |
mstore(0x20, p0) |
||
| 8929 |
mstore(0x40, p1) |
||
| 8930 |
mstore(0x60, p2) |
||
| 8931 |
mstore(0x80, p3) |
||
| 8932 |
} |
||
| 8933 |
_sendLogPayload(0x1c, 0x84); |
||
| 8934 |
/// @solidity memory-safe-assembly |
||
| 8935 |
assembly {
|
||
| 8936 |
mstore(0x00, m0) |
||
| 8937 |
mstore(0x20, m1) |
||
| 8938 |
mstore(0x40, m2) |
||
| 8939 |
mstore(0x60, m3) |
||
| 8940 |
mstore(0x80, m4) |
||
| 8941 |
} |
||
| 8942 |
} |
||
| 8943 | |||
| 8944 |
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
|
||
| 8945 |
bytes32 m0; |
||
| 8946 |
bytes32 m1; |
||
| 8947 |
bytes32 m2; |
||
| 8948 |
bytes32 m3; |
||
| 8949 |
bytes32 m4; |
||
| 8950 |
/// @solidity memory-safe-assembly |
||
| 8951 |
assembly {
|
||
| 8952 |
m0 := mload(0x00) |
||
| 8953 |
m1 := mload(0x20) |
||
| 8954 |
m2 := mload(0x40) |
||
| 8955 |
m3 := mload(0x60) |
||
| 8956 |
m4 := mload(0x80) |
||
| 8957 |
// Selector of `log(uint256,bool,bool,uint256)`. |
||
| 8958 |
mstore(0x00, 0x7464ce23) |
||
| 8959 |
mstore(0x20, p0) |
||
| 8960 |
mstore(0x40, p1) |
||
| 8961 |
mstore(0x60, p2) |
||
| 8962 |
mstore(0x80, p3) |
||
| 8963 |
} |
||
| 8964 |
_sendLogPayload(0x1c, 0x84); |
||
| 8965 |
/// @solidity memory-safe-assembly |
||
| 8966 |
assembly {
|
||
| 8967 |
mstore(0x00, m0) |
||
| 8968 |
mstore(0x20, m1) |
||
| 8969 |
mstore(0x40, m2) |
||
| 8970 |
mstore(0x60, m3) |
||
| 8971 |
mstore(0x80, m4) |
||
| 8972 |
} |
||
| 8973 |
} |
||
| 8974 | |||
| 8975 |
function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure {
|
||
| 8976 |
bytes32 m0; |
||
| 8977 |
bytes32 m1; |
||
| 8978 |
bytes32 m2; |
||
| 8979 |
bytes32 m3; |
||
| 8980 |
bytes32 m4; |
||
| 8981 |
bytes32 m5; |
||
| 8982 |
bytes32 m6; |
||
| 8983 |
/// @solidity memory-safe-assembly |
||
| 8984 |
assembly {
|
||
| 8985 |
function writeString(pos, w) {
|
||
| 8986 |
let length := 0 |
||
| 8987 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 8988 |
mstore(pos, length) |
||
| 8989 |
let shift := sub(256, shl(3, length)) |
||
| 8990 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 8991 |
} |
||
| 8992 |
m0 := mload(0x00) |
||
| 8993 |
m1 := mload(0x20) |
||
| 8994 |
m2 := mload(0x40) |
||
| 8995 |
m3 := mload(0x60) |
||
| 8996 |
m4 := mload(0x80) |
||
| 8997 |
m5 := mload(0xa0) |
||
| 8998 |
m6 := mload(0xc0) |
||
| 8999 |
// Selector of `log(uint256,bool,bool,string)`. |
||
| 9000 |
mstore(0x00, 0xdddb9561) |
||
| 9001 |
mstore(0x20, p0) |
||
| 9002 |
mstore(0x40, p1) |
||
| 9003 |
mstore(0x60, p2) |
||
| 9004 |
mstore(0x80, 0x80) |
||
| 9005 |
writeString(0xa0, p3) |
||
| 9006 |
} |
||
| 9007 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9008 |
/// @solidity memory-safe-assembly |
||
| 9009 |
assembly {
|
||
| 9010 |
mstore(0x00, m0) |
||
| 9011 |
mstore(0x20, m1) |
||
| 9012 |
mstore(0x40, m2) |
||
| 9013 |
mstore(0x60, m3) |
||
| 9014 |
mstore(0x80, m4) |
||
| 9015 |
mstore(0xa0, m5) |
||
| 9016 |
mstore(0xc0, m6) |
||
| 9017 |
} |
||
| 9018 |
} |
||
| 9019 | |||
| 9020 |
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
|
||
| 9021 |
bytes32 m0; |
||
| 9022 |
bytes32 m1; |
||
| 9023 |
bytes32 m2; |
||
| 9024 |
bytes32 m3; |
||
| 9025 |
bytes32 m4; |
||
| 9026 |
/// @solidity memory-safe-assembly |
||
| 9027 |
assembly {
|
||
| 9028 |
m0 := mload(0x00) |
||
| 9029 |
m1 := mload(0x20) |
||
| 9030 |
m2 := mload(0x40) |
||
| 9031 |
m3 := mload(0x60) |
||
| 9032 |
m4 := mload(0x80) |
||
| 9033 |
// Selector of `log(uint256,bool,uint256,address)`. |
||
| 9034 |
mstore(0x00, 0x88cb6041) |
||
| 9035 |
mstore(0x20, p0) |
||
| 9036 |
mstore(0x40, p1) |
||
| 9037 |
mstore(0x60, p2) |
||
| 9038 |
mstore(0x80, p3) |
||
| 9039 |
} |
||
| 9040 |
_sendLogPayload(0x1c, 0x84); |
||
| 9041 |
/// @solidity memory-safe-assembly |
||
| 9042 |
assembly {
|
||
| 9043 |
mstore(0x00, m0) |
||
| 9044 |
mstore(0x20, m1) |
||
| 9045 |
mstore(0x40, m2) |
||
| 9046 |
mstore(0x60, m3) |
||
| 9047 |
mstore(0x80, m4) |
||
| 9048 |
} |
||
| 9049 |
} |
||
| 9050 | |||
| 9051 |
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
|
||
| 9052 |
bytes32 m0; |
||
| 9053 |
bytes32 m1; |
||
| 9054 |
bytes32 m2; |
||
| 9055 |
bytes32 m3; |
||
| 9056 |
bytes32 m4; |
||
| 9057 |
/// @solidity memory-safe-assembly |
||
| 9058 |
assembly {
|
||
| 9059 |
m0 := mload(0x00) |
||
| 9060 |
m1 := mload(0x20) |
||
| 9061 |
m2 := mload(0x40) |
||
| 9062 |
m3 := mload(0x60) |
||
| 9063 |
m4 := mload(0x80) |
||
| 9064 |
// Selector of `log(uint256,bool,uint256,bool)`. |
||
| 9065 |
mstore(0x00, 0x91a02e2a) |
||
| 9066 |
mstore(0x20, p0) |
||
| 9067 |
mstore(0x40, p1) |
||
| 9068 |
mstore(0x60, p2) |
||
| 9069 |
mstore(0x80, p3) |
||
| 9070 |
} |
||
| 9071 |
_sendLogPayload(0x1c, 0x84); |
||
| 9072 |
/// @solidity memory-safe-assembly |
||
| 9073 |
assembly {
|
||
| 9074 |
mstore(0x00, m0) |
||
| 9075 |
mstore(0x20, m1) |
||
| 9076 |
mstore(0x40, m2) |
||
| 9077 |
mstore(0x60, m3) |
||
| 9078 |
mstore(0x80, m4) |
||
| 9079 |
} |
||
| 9080 |
} |
||
| 9081 | |||
| 9082 |
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
|
||
| 9083 |
bytes32 m0; |
||
| 9084 |
bytes32 m1; |
||
| 9085 |
bytes32 m2; |
||
| 9086 |
bytes32 m3; |
||
| 9087 |
bytes32 m4; |
||
| 9088 |
/// @solidity memory-safe-assembly |
||
| 9089 |
assembly {
|
||
| 9090 |
m0 := mload(0x00) |
||
| 9091 |
m1 := mload(0x20) |
||
| 9092 |
m2 := mload(0x40) |
||
| 9093 |
m3 := mload(0x60) |
||
| 9094 |
m4 := mload(0x80) |
||
| 9095 |
// Selector of `log(uint256,bool,uint256,uint256)`. |
||
| 9096 |
mstore(0x00, 0xc6acc7a8) |
||
| 9097 |
mstore(0x20, p0) |
||
| 9098 |
mstore(0x40, p1) |
||
| 9099 |
mstore(0x60, p2) |
||
| 9100 |
mstore(0x80, p3) |
||
| 9101 |
} |
||
| 9102 |
_sendLogPayload(0x1c, 0x84); |
||
| 9103 |
/// @solidity memory-safe-assembly |
||
| 9104 |
assembly {
|
||
| 9105 |
mstore(0x00, m0) |
||
| 9106 |
mstore(0x20, m1) |
||
| 9107 |
mstore(0x40, m2) |
||
| 9108 |
mstore(0x60, m3) |
||
| 9109 |
mstore(0x80, m4) |
||
| 9110 |
} |
||
| 9111 |
} |
||
| 9112 | |||
| 9113 |
function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 9114 |
bytes32 m0; |
||
| 9115 |
bytes32 m1; |
||
| 9116 |
bytes32 m2; |
||
| 9117 |
bytes32 m3; |
||
| 9118 |
bytes32 m4; |
||
| 9119 |
bytes32 m5; |
||
| 9120 |
bytes32 m6; |
||
| 9121 |
/// @solidity memory-safe-assembly |
||
| 9122 |
assembly {
|
||
| 9123 |
function writeString(pos, w) {
|
||
| 9124 |
let length := 0 |
||
| 9125 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9126 |
mstore(pos, length) |
||
| 9127 |
let shift := sub(256, shl(3, length)) |
||
| 9128 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9129 |
} |
||
| 9130 |
m0 := mload(0x00) |
||
| 9131 |
m1 := mload(0x20) |
||
| 9132 |
m2 := mload(0x40) |
||
| 9133 |
m3 := mload(0x60) |
||
| 9134 |
m4 := mload(0x80) |
||
| 9135 |
m5 := mload(0xa0) |
||
| 9136 |
m6 := mload(0xc0) |
||
| 9137 |
// Selector of `log(uint256,bool,uint256,string)`. |
||
| 9138 |
mstore(0x00, 0xde03e774) |
||
| 9139 |
mstore(0x20, p0) |
||
| 9140 |
mstore(0x40, p1) |
||
| 9141 |
mstore(0x60, p2) |
||
| 9142 |
mstore(0x80, 0x80) |
||
| 9143 |
writeString(0xa0, p3) |
||
| 9144 |
} |
||
| 9145 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9146 |
/// @solidity memory-safe-assembly |
||
| 9147 |
assembly {
|
||
| 9148 |
mstore(0x00, m0) |
||
| 9149 |
mstore(0x20, m1) |
||
| 9150 |
mstore(0x40, m2) |
||
| 9151 |
mstore(0x60, m3) |
||
| 9152 |
mstore(0x80, m4) |
||
| 9153 |
mstore(0xa0, m5) |
||
| 9154 |
mstore(0xc0, m6) |
||
| 9155 |
} |
||
| 9156 |
} |
||
| 9157 | |||
| 9158 |
function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure {
|
||
| 9159 |
bytes32 m0; |
||
| 9160 |
bytes32 m1; |
||
| 9161 |
bytes32 m2; |
||
| 9162 |
bytes32 m3; |
||
| 9163 |
bytes32 m4; |
||
| 9164 |
bytes32 m5; |
||
| 9165 |
bytes32 m6; |
||
| 9166 |
/// @solidity memory-safe-assembly |
||
| 9167 |
assembly {
|
||
| 9168 |
function writeString(pos, w) {
|
||
| 9169 |
let length := 0 |
||
| 9170 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9171 |
mstore(pos, length) |
||
| 9172 |
let shift := sub(256, shl(3, length)) |
||
| 9173 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9174 |
} |
||
| 9175 |
m0 := mload(0x00) |
||
| 9176 |
m1 := mload(0x20) |
||
| 9177 |
m2 := mload(0x40) |
||
| 9178 |
m3 := mload(0x60) |
||
| 9179 |
m4 := mload(0x80) |
||
| 9180 |
m5 := mload(0xa0) |
||
| 9181 |
m6 := mload(0xc0) |
||
| 9182 |
// Selector of `log(uint256,bool,string,address)`. |
||
| 9183 |
mstore(0x00, 0xef529018) |
||
| 9184 |
mstore(0x20, p0) |
||
| 9185 |
mstore(0x40, p1) |
||
| 9186 |
mstore(0x60, 0x80) |
||
| 9187 |
mstore(0x80, p3) |
||
| 9188 |
writeString(0xa0, p2) |
||
| 9189 |
} |
||
| 9190 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9191 |
/// @solidity memory-safe-assembly |
||
| 9192 |
assembly {
|
||
| 9193 |
mstore(0x00, m0) |
||
| 9194 |
mstore(0x20, m1) |
||
| 9195 |
mstore(0x40, m2) |
||
| 9196 |
mstore(0x60, m3) |
||
| 9197 |
mstore(0x80, m4) |
||
| 9198 |
mstore(0xa0, m5) |
||
| 9199 |
mstore(0xc0, m6) |
||
| 9200 |
} |
||
| 9201 |
} |
||
| 9202 | |||
| 9203 |
function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure {
|
||
| 9204 |
bytes32 m0; |
||
| 9205 |
bytes32 m1; |
||
| 9206 |
bytes32 m2; |
||
| 9207 |
bytes32 m3; |
||
| 9208 |
bytes32 m4; |
||
| 9209 |
bytes32 m5; |
||
| 9210 |
bytes32 m6; |
||
| 9211 |
/// @solidity memory-safe-assembly |
||
| 9212 |
assembly {
|
||
| 9213 |
function writeString(pos, w) {
|
||
| 9214 |
let length := 0 |
||
| 9215 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9216 |
mstore(pos, length) |
||
| 9217 |
let shift := sub(256, shl(3, length)) |
||
| 9218 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9219 |
} |
||
| 9220 |
m0 := mload(0x00) |
||
| 9221 |
m1 := mload(0x20) |
||
| 9222 |
m2 := mload(0x40) |
||
| 9223 |
m3 := mload(0x60) |
||
| 9224 |
m4 := mload(0x80) |
||
| 9225 |
m5 := mload(0xa0) |
||
| 9226 |
m6 := mload(0xc0) |
||
| 9227 |
// Selector of `log(uint256,bool,string,bool)`. |
||
| 9228 |
mstore(0x00, 0xeb928d7f) |
||
| 9229 |
mstore(0x20, p0) |
||
| 9230 |
mstore(0x40, p1) |
||
| 9231 |
mstore(0x60, 0x80) |
||
| 9232 |
mstore(0x80, p3) |
||
| 9233 |
writeString(0xa0, p2) |
||
| 9234 |
} |
||
| 9235 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9236 |
/// @solidity memory-safe-assembly |
||
| 9237 |
assembly {
|
||
| 9238 |
mstore(0x00, m0) |
||
| 9239 |
mstore(0x20, m1) |
||
| 9240 |
mstore(0x40, m2) |
||
| 9241 |
mstore(0x60, m3) |
||
| 9242 |
mstore(0x80, m4) |
||
| 9243 |
mstore(0xa0, m5) |
||
| 9244 |
mstore(0xc0, m6) |
||
| 9245 |
} |
||
| 9246 |
} |
||
| 9247 | |||
| 9248 |
function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 9249 |
bytes32 m0; |
||
| 9250 |
bytes32 m1; |
||
| 9251 |
bytes32 m2; |
||
| 9252 |
bytes32 m3; |
||
| 9253 |
bytes32 m4; |
||
| 9254 |
bytes32 m5; |
||
| 9255 |
bytes32 m6; |
||
| 9256 |
/// @solidity memory-safe-assembly |
||
| 9257 |
assembly {
|
||
| 9258 |
function writeString(pos, w) {
|
||
| 9259 |
let length := 0 |
||
| 9260 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9261 |
mstore(pos, length) |
||
| 9262 |
let shift := sub(256, shl(3, length)) |
||
| 9263 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9264 |
} |
||
| 9265 |
m0 := mload(0x00) |
||
| 9266 |
m1 := mload(0x20) |
||
| 9267 |
m2 := mload(0x40) |
||
| 9268 |
m3 := mload(0x60) |
||
| 9269 |
m4 := mload(0x80) |
||
| 9270 |
m5 := mload(0xa0) |
||
| 9271 |
m6 := mload(0xc0) |
||
| 9272 |
// Selector of `log(uint256,bool,string,uint256)`. |
||
| 9273 |
mstore(0x00, 0x2c1d0746) |
||
| 9274 |
mstore(0x20, p0) |
||
| 9275 |
mstore(0x40, p1) |
||
| 9276 |
mstore(0x60, 0x80) |
||
| 9277 |
mstore(0x80, p3) |
||
| 9278 |
writeString(0xa0, p2) |
||
| 9279 |
} |
||
| 9280 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9281 |
/// @solidity memory-safe-assembly |
||
| 9282 |
assembly {
|
||
| 9283 |
mstore(0x00, m0) |
||
| 9284 |
mstore(0x20, m1) |
||
| 9285 |
mstore(0x40, m2) |
||
| 9286 |
mstore(0x60, m3) |
||
| 9287 |
mstore(0x80, m4) |
||
| 9288 |
mstore(0xa0, m5) |
||
| 9289 |
mstore(0xc0, m6) |
||
| 9290 |
} |
||
| 9291 |
} |
||
| 9292 | |||
| 9293 |
function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 9294 |
bytes32 m0; |
||
| 9295 |
bytes32 m1; |
||
| 9296 |
bytes32 m2; |
||
| 9297 |
bytes32 m3; |
||
| 9298 |
bytes32 m4; |
||
| 9299 |
bytes32 m5; |
||
| 9300 |
bytes32 m6; |
||
| 9301 |
bytes32 m7; |
||
| 9302 |
bytes32 m8; |
||
| 9303 |
/// @solidity memory-safe-assembly |
||
| 9304 |
assembly {
|
||
| 9305 |
function writeString(pos, w) {
|
||
| 9306 |
let length := 0 |
||
| 9307 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9308 |
mstore(pos, length) |
||
| 9309 |
let shift := sub(256, shl(3, length)) |
||
| 9310 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9311 |
} |
||
| 9312 |
m0 := mload(0x00) |
||
| 9313 |
m1 := mload(0x20) |
||
| 9314 |
m2 := mload(0x40) |
||
| 9315 |
m3 := mload(0x60) |
||
| 9316 |
m4 := mload(0x80) |
||
| 9317 |
m5 := mload(0xa0) |
||
| 9318 |
m6 := mload(0xc0) |
||
| 9319 |
m7 := mload(0xe0) |
||
| 9320 |
m8 := mload(0x100) |
||
| 9321 |
// Selector of `log(uint256,bool,string,string)`. |
||
| 9322 |
mstore(0x00, 0x68c8b8bd) |
||
| 9323 |
mstore(0x20, p0) |
||
| 9324 |
mstore(0x40, p1) |
||
| 9325 |
mstore(0x60, 0x80) |
||
| 9326 |
mstore(0x80, 0xc0) |
||
| 9327 |
writeString(0xa0, p2) |
||
| 9328 |
writeString(0xe0, p3) |
||
| 9329 |
} |
||
| 9330 |
_sendLogPayload(0x1c, 0x104); |
||
| 9331 |
/// @solidity memory-safe-assembly |
||
| 9332 |
assembly {
|
||
| 9333 |
mstore(0x00, m0) |
||
| 9334 |
mstore(0x20, m1) |
||
| 9335 |
mstore(0x40, m2) |
||
| 9336 |
mstore(0x60, m3) |
||
| 9337 |
mstore(0x80, m4) |
||
| 9338 |
mstore(0xa0, m5) |
||
| 9339 |
mstore(0xc0, m6) |
||
| 9340 |
mstore(0xe0, m7) |
||
| 9341 |
mstore(0x100, m8) |
||
| 9342 |
} |
||
| 9343 |
} |
||
| 9344 | |||
| 9345 |
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
|
||
| 9346 |
bytes32 m0; |
||
| 9347 |
bytes32 m1; |
||
| 9348 |
bytes32 m2; |
||
| 9349 |
bytes32 m3; |
||
| 9350 |
bytes32 m4; |
||
| 9351 |
/// @solidity memory-safe-assembly |
||
| 9352 |
assembly {
|
||
| 9353 |
m0 := mload(0x00) |
||
| 9354 |
m1 := mload(0x20) |
||
| 9355 |
m2 := mload(0x40) |
||
| 9356 |
m3 := mload(0x60) |
||
| 9357 |
m4 := mload(0x80) |
||
| 9358 |
// Selector of `log(uint256,uint256,address,address)`. |
||
| 9359 |
mstore(0x00, 0x56a5d1b1) |
||
| 9360 |
mstore(0x20, p0) |
||
| 9361 |
mstore(0x40, p1) |
||
| 9362 |
mstore(0x60, p2) |
||
| 9363 |
mstore(0x80, p3) |
||
| 9364 |
} |
||
| 9365 |
_sendLogPayload(0x1c, 0x84); |
||
| 9366 |
/// @solidity memory-safe-assembly |
||
| 9367 |
assembly {
|
||
| 9368 |
mstore(0x00, m0) |
||
| 9369 |
mstore(0x20, m1) |
||
| 9370 |
mstore(0x40, m2) |
||
| 9371 |
mstore(0x60, m3) |
||
| 9372 |
mstore(0x80, m4) |
||
| 9373 |
} |
||
| 9374 |
} |
||
| 9375 | |||
| 9376 |
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
|
||
| 9377 |
bytes32 m0; |
||
| 9378 |
bytes32 m1; |
||
| 9379 |
bytes32 m2; |
||
| 9380 |
bytes32 m3; |
||
| 9381 |
bytes32 m4; |
||
| 9382 |
/// @solidity memory-safe-assembly |
||
| 9383 |
assembly {
|
||
| 9384 |
m0 := mload(0x00) |
||
| 9385 |
m1 := mload(0x20) |
||
| 9386 |
m2 := mload(0x40) |
||
| 9387 |
m3 := mload(0x60) |
||
| 9388 |
m4 := mload(0x80) |
||
| 9389 |
// Selector of `log(uint256,uint256,address,bool)`. |
||
| 9390 |
mstore(0x00, 0x15cac476) |
||
| 9391 |
mstore(0x20, p0) |
||
| 9392 |
mstore(0x40, p1) |
||
| 9393 |
mstore(0x60, p2) |
||
| 9394 |
mstore(0x80, p3) |
||
| 9395 |
} |
||
| 9396 |
_sendLogPayload(0x1c, 0x84); |
||
| 9397 |
/// @solidity memory-safe-assembly |
||
| 9398 |
assembly {
|
||
| 9399 |
mstore(0x00, m0) |
||
| 9400 |
mstore(0x20, m1) |
||
| 9401 |
mstore(0x40, m2) |
||
| 9402 |
mstore(0x60, m3) |
||
| 9403 |
mstore(0x80, m4) |
||
| 9404 |
} |
||
| 9405 |
} |
||
| 9406 | |||
| 9407 |
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
|
||
| 9408 |
bytes32 m0; |
||
| 9409 |
bytes32 m1; |
||
| 9410 |
bytes32 m2; |
||
| 9411 |
bytes32 m3; |
||
| 9412 |
bytes32 m4; |
||
| 9413 |
/// @solidity memory-safe-assembly |
||
| 9414 |
assembly {
|
||
| 9415 |
m0 := mload(0x00) |
||
| 9416 |
m1 := mload(0x20) |
||
| 9417 |
m2 := mload(0x40) |
||
| 9418 |
m3 := mload(0x60) |
||
| 9419 |
m4 := mload(0x80) |
||
| 9420 |
// Selector of `log(uint256,uint256,address,uint256)`. |
||
| 9421 |
mstore(0x00, 0x88f6e4b2) |
||
| 9422 |
mstore(0x20, p0) |
||
| 9423 |
mstore(0x40, p1) |
||
| 9424 |
mstore(0x60, p2) |
||
| 9425 |
mstore(0x80, p3) |
||
| 9426 |
} |
||
| 9427 |
_sendLogPayload(0x1c, 0x84); |
||
| 9428 |
/// @solidity memory-safe-assembly |
||
| 9429 |
assembly {
|
||
| 9430 |
mstore(0x00, m0) |
||
| 9431 |
mstore(0x20, m1) |
||
| 9432 |
mstore(0x40, m2) |
||
| 9433 |
mstore(0x60, m3) |
||
| 9434 |
mstore(0x80, m4) |
||
| 9435 |
} |
||
| 9436 |
} |
||
| 9437 | |||
| 9438 |
function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure {
|
||
| 9439 |
bytes32 m0; |
||
| 9440 |
bytes32 m1; |
||
| 9441 |
bytes32 m2; |
||
| 9442 |
bytes32 m3; |
||
| 9443 |
bytes32 m4; |
||
| 9444 |
bytes32 m5; |
||
| 9445 |
bytes32 m6; |
||
| 9446 |
/// @solidity memory-safe-assembly |
||
| 9447 |
assembly {
|
||
| 9448 |
function writeString(pos, w) {
|
||
| 9449 |
let length := 0 |
||
| 9450 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9451 |
mstore(pos, length) |
||
| 9452 |
let shift := sub(256, shl(3, length)) |
||
| 9453 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9454 |
} |
||
| 9455 |
m0 := mload(0x00) |
||
| 9456 |
m1 := mload(0x20) |
||
| 9457 |
m2 := mload(0x40) |
||
| 9458 |
m3 := mload(0x60) |
||
| 9459 |
m4 := mload(0x80) |
||
| 9460 |
m5 := mload(0xa0) |
||
| 9461 |
m6 := mload(0xc0) |
||
| 9462 |
// Selector of `log(uint256,uint256,address,string)`. |
||
| 9463 |
mstore(0x00, 0x6cde40b8) |
||
| 9464 |
mstore(0x20, p0) |
||
| 9465 |
mstore(0x40, p1) |
||
| 9466 |
mstore(0x60, p2) |
||
| 9467 |
mstore(0x80, 0x80) |
||
| 9468 |
writeString(0xa0, p3) |
||
| 9469 |
} |
||
| 9470 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9471 |
/// @solidity memory-safe-assembly |
||
| 9472 |
assembly {
|
||
| 9473 |
mstore(0x00, m0) |
||
| 9474 |
mstore(0x20, m1) |
||
| 9475 |
mstore(0x40, m2) |
||
| 9476 |
mstore(0x60, m3) |
||
| 9477 |
mstore(0x80, m4) |
||
| 9478 |
mstore(0xa0, m5) |
||
| 9479 |
mstore(0xc0, m6) |
||
| 9480 |
} |
||
| 9481 |
} |
||
| 9482 | |||
| 9483 |
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
|
||
| 9484 |
bytes32 m0; |
||
| 9485 |
bytes32 m1; |
||
| 9486 |
bytes32 m2; |
||
| 9487 |
bytes32 m3; |
||
| 9488 |
bytes32 m4; |
||
| 9489 |
/// @solidity memory-safe-assembly |
||
| 9490 |
assembly {
|
||
| 9491 |
m0 := mload(0x00) |
||
| 9492 |
m1 := mload(0x20) |
||
| 9493 |
m2 := mload(0x40) |
||
| 9494 |
m3 := mload(0x60) |
||
| 9495 |
m4 := mload(0x80) |
||
| 9496 |
// Selector of `log(uint256,uint256,bool,address)`. |
||
| 9497 |
mstore(0x00, 0x9a816a83) |
||
| 9498 |
mstore(0x20, p0) |
||
| 9499 |
mstore(0x40, p1) |
||
| 9500 |
mstore(0x60, p2) |
||
| 9501 |
mstore(0x80, p3) |
||
| 9502 |
} |
||
| 9503 |
_sendLogPayload(0x1c, 0x84); |
||
| 9504 |
/// @solidity memory-safe-assembly |
||
| 9505 |
assembly {
|
||
| 9506 |
mstore(0x00, m0) |
||
| 9507 |
mstore(0x20, m1) |
||
| 9508 |
mstore(0x40, m2) |
||
| 9509 |
mstore(0x60, m3) |
||
| 9510 |
mstore(0x80, m4) |
||
| 9511 |
} |
||
| 9512 |
} |
||
| 9513 | |||
| 9514 |
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
|
||
| 9515 |
bytes32 m0; |
||
| 9516 |
bytes32 m1; |
||
| 9517 |
bytes32 m2; |
||
| 9518 |
bytes32 m3; |
||
| 9519 |
bytes32 m4; |
||
| 9520 |
/// @solidity memory-safe-assembly |
||
| 9521 |
assembly {
|
||
| 9522 |
m0 := mload(0x00) |
||
| 9523 |
m1 := mload(0x20) |
||
| 9524 |
m2 := mload(0x40) |
||
| 9525 |
m3 := mload(0x60) |
||
| 9526 |
m4 := mload(0x80) |
||
| 9527 |
// Selector of `log(uint256,uint256,bool,bool)`. |
||
| 9528 |
mstore(0x00, 0xab085ae6) |
||
| 9529 |
mstore(0x20, p0) |
||
| 9530 |
mstore(0x40, p1) |
||
| 9531 |
mstore(0x60, p2) |
||
| 9532 |
mstore(0x80, p3) |
||
| 9533 |
} |
||
| 9534 |
_sendLogPayload(0x1c, 0x84); |
||
| 9535 |
/// @solidity memory-safe-assembly |
||
| 9536 |
assembly {
|
||
| 9537 |
mstore(0x00, m0) |
||
| 9538 |
mstore(0x20, m1) |
||
| 9539 |
mstore(0x40, m2) |
||
| 9540 |
mstore(0x60, m3) |
||
| 9541 |
mstore(0x80, m4) |
||
| 9542 |
} |
||
| 9543 |
} |
||
| 9544 | |||
| 9545 |
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
|
||
| 9546 |
bytes32 m0; |
||
| 9547 |
bytes32 m1; |
||
| 9548 |
bytes32 m2; |
||
| 9549 |
bytes32 m3; |
||
| 9550 |
bytes32 m4; |
||
| 9551 |
/// @solidity memory-safe-assembly |
||
| 9552 |
assembly {
|
||
| 9553 |
m0 := mload(0x00) |
||
| 9554 |
m1 := mload(0x20) |
||
| 9555 |
m2 := mload(0x40) |
||
| 9556 |
m3 := mload(0x60) |
||
| 9557 |
m4 := mload(0x80) |
||
| 9558 |
// Selector of `log(uint256,uint256,bool,uint256)`. |
||
| 9559 |
mstore(0x00, 0xeb7f6fd2) |
||
| 9560 |
mstore(0x20, p0) |
||
| 9561 |
mstore(0x40, p1) |
||
| 9562 |
mstore(0x60, p2) |
||
| 9563 |
mstore(0x80, p3) |
||
| 9564 |
} |
||
| 9565 |
_sendLogPayload(0x1c, 0x84); |
||
| 9566 |
/// @solidity memory-safe-assembly |
||
| 9567 |
assembly {
|
||
| 9568 |
mstore(0x00, m0) |
||
| 9569 |
mstore(0x20, m1) |
||
| 9570 |
mstore(0x40, m2) |
||
| 9571 |
mstore(0x60, m3) |
||
| 9572 |
mstore(0x80, m4) |
||
| 9573 |
} |
||
| 9574 |
} |
||
| 9575 | |||
| 9576 |
function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
|
||
| 9577 |
bytes32 m0; |
||
| 9578 |
bytes32 m1; |
||
| 9579 |
bytes32 m2; |
||
| 9580 |
bytes32 m3; |
||
| 9581 |
bytes32 m4; |
||
| 9582 |
bytes32 m5; |
||
| 9583 |
bytes32 m6; |
||
| 9584 |
/// @solidity memory-safe-assembly |
||
| 9585 |
assembly {
|
||
| 9586 |
function writeString(pos, w) {
|
||
| 9587 |
let length := 0 |
||
| 9588 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9589 |
mstore(pos, length) |
||
| 9590 |
let shift := sub(256, shl(3, length)) |
||
| 9591 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9592 |
} |
||
| 9593 |
m0 := mload(0x00) |
||
| 9594 |
m1 := mload(0x20) |
||
| 9595 |
m2 := mload(0x40) |
||
| 9596 |
m3 := mload(0x60) |
||
| 9597 |
m4 := mload(0x80) |
||
| 9598 |
m5 := mload(0xa0) |
||
| 9599 |
m6 := mload(0xc0) |
||
| 9600 |
// Selector of `log(uint256,uint256,bool,string)`. |
||
| 9601 |
mstore(0x00, 0xa5b4fc99) |
||
| 9602 |
mstore(0x20, p0) |
||
| 9603 |
mstore(0x40, p1) |
||
| 9604 |
mstore(0x60, p2) |
||
| 9605 |
mstore(0x80, 0x80) |
||
| 9606 |
writeString(0xa0, p3) |
||
| 9607 |
} |
||
| 9608 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9609 |
/// @solidity memory-safe-assembly |
||
| 9610 |
assembly {
|
||
| 9611 |
mstore(0x00, m0) |
||
| 9612 |
mstore(0x20, m1) |
||
| 9613 |
mstore(0x40, m2) |
||
| 9614 |
mstore(0x60, m3) |
||
| 9615 |
mstore(0x80, m4) |
||
| 9616 |
mstore(0xa0, m5) |
||
| 9617 |
mstore(0xc0, m6) |
||
| 9618 |
} |
||
| 9619 |
} |
||
| 9620 | |||
| 9621 |
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
|
||
| 9622 |
bytes32 m0; |
||
| 9623 |
bytes32 m1; |
||
| 9624 |
bytes32 m2; |
||
| 9625 |
bytes32 m3; |
||
| 9626 |
bytes32 m4; |
||
| 9627 |
/// @solidity memory-safe-assembly |
||
| 9628 |
assembly {
|
||
| 9629 |
m0 := mload(0x00) |
||
| 9630 |
m1 := mload(0x20) |
||
| 9631 |
m2 := mload(0x40) |
||
| 9632 |
m3 := mload(0x60) |
||
| 9633 |
m4 := mload(0x80) |
||
| 9634 |
// Selector of `log(uint256,uint256,uint256,address)`. |
||
| 9635 |
mstore(0x00, 0xfa8185af) |
||
| 9636 |
mstore(0x20, p0) |
||
| 9637 |
mstore(0x40, p1) |
||
| 9638 |
mstore(0x60, p2) |
||
| 9639 |
mstore(0x80, p3) |
||
| 9640 |
} |
||
| 9641 |
_sendLogPayload(0x1c, 0x84); |
||
| 9642 |
/// @solidity memory-safe-assembly |
||
| 9643 |
assembly {
|
||
| 9644 |
mstore(0x00, m0) |
||
| 9645 |
mstore(0x20, m1) |
||
| 9646 |
mstore(0x40, m2) |
||
| 9647 |
mstore(0x60, m3) |
||
| 9648 |
mstore(0x80, m4) |
||
| 9649 |
} |
||
| 9650 |
} |
||
| 9651 | |||
| 9652 |
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
|
||
| 9653 |
bytes32 m0; |
||
| 9654 |
bytes32 m1; |
||
| 9655 |
bytes32 m2; |
||
| 9656 |
bytes32 m3; |
||
| 9657 |
bytes32 m4; |
||
| 9658 |
/// @solidity memory-safe-assembly |
||
| 9659 |
assembly {
|
||
| 9660 |
m0 := mload(0x00) |
||
| 9661 |
m1 := mload(0x20) |
||
| 9662 |
m2 := mload(0x40) |
||
| 9663 |
m3 := mload(0x60) |
||
| 9664 |
m4 := mload(0x80) |
||
| 9665 |
// Selector of `log(uint256,uint256,uint256,bool)`. |
||
| 9666 |
mstore(0x00, 0xc598d185) |
||
| 9667 |
mstore(0x20, p0) |
||
| 9668 |
mstore(0x40, p1) |
||
| 9669 |
mstore(0x60, p2) |
||
| 9670 |
mstore(0x80, p3) |
||
| 9671 |
} |
||
| 9672 |
_sendLogPayload(0x1c, 0x84); |
||
| 9673 |
/// @solidity memory-safe-assembly |
||
| 9674 |
assembly {
|
||
| 9675 |
mstore(0x00, m0) |
||
| 9676 |
mstore(0x20, m1) |
||
| 9677 |
mstore(0x40, m2) |
||
| 9678 |
mstore(0x60, m3) |
||
| 9679 |
mstore(0x80, m4) |
||
| 9680 |
} |
||
| 9681 |
} |
||
| 9682 | |||
| 9683 |
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 9684 |
bytes32 m0; |
||
| 9685 |
bytes32 m1; |
||
| 9686 |
bytes32 m2; |
||
| 9687 |
bytes32 m3; |
||
| 9688 |
bytes32 m4; |
||
| 9689 |
/// @solidity memory-safe-assembly |
||
| 9690 |
assembly {
|
||
| 9691 |
m0 := mload(0x00) |
||
| 9692 |
m1 := mload(0x20) |
||
| 9693 |
m2 := mload(0x40) |
||
| 9694 |
m3 := mload(0x60) |
||
| 9695 |
m4 := mload(0x80) |
||
| 9696 |
// Selector of `log(uint256,uint256,uint256,uint256)`. |
||
| 9697 |
mstore(0x00, 0x193fb800) |
||
| 9698 |
mstore(0x20, p0) |
||
| 9699 |
mstore(0x40, p1) |
||
| 9700 |
mstore(0x60, p2) |
||
| 9701 |
mstore(0x80, p3) |
||
| 9702 |
} |
||
| 9703 |
_sendLogPayload(0x1c, 0x84); |
||
| 9704 |
/// @solidity memory-safe-assembly |
||
| 9705 |
assembly {
|
||
| 9706 |
mstore(0x00, m0) |
||
| 9707 |
mstore(0x20, m1) |
||
| 9708 |
mstore(0x40, m2) |
||
| 9709 |
mstore(0x60, m3) |
||
| 9710 |
mstore(0x80, m4) |
||
| 9711 |
} |
||
| 9712 |
} |
||
| 9713 | |||
| 9714 |
function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 9715 |
bytes32 m0; |
||
| 9716 |
bytes32 m1; |
||
| 9717 |
bytes32 m2; |
||
| 9718 |
bytes32 m3; |
||
| 9719 |
bytes32 m4; |
||
| 9720 |
bytes32 m5; |
||
| 9721 |
bytes32 m6; |
||
| 9722 |
/// @solidity memory-safe-assembly |
||
| 9723 |
assembly {
|
||
| 9724 |
function writeString(pos, w) {
|
||
| 9725 |
let length := 0 |
||
| 9726 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9727 |
mstore(pos, length) |
||
| 9728 |
let shift := sub(256, shl(3, length)) |
||
| 9729 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9730 |
} |
||
| 9731 |
m0 := mload(0x00) |
||
| 9732 |
m1 := mload(0x20) |
||
| 9733 |
m2 := mload(0x40) |
||
| 9734 |
m3 := mload(0x60) |
||
| 9735 |
m4 := mload(0x80) |
||
| 9736 |
m5 := mload(0xa0) |
||
| 9737 |
m6 := mload(0xc0) |
||
| 9738 |
// Selector of `log(uint256,uint256,uint256,string)`. |
||
| 9739 |
mstore(0x00, 0x59cfcbe3) |
||
| 9740 |
mstore(0x20, p0) |
||
| 9741 |
mstore(0x40, p1) |
||
| 9742 |
mstore(0x60, p2) |
||
| 9743 |
mstore(0x80, 0x80) |
||
| 9744 |
writeString(0xa0, p3) |
||
| 9745 |
} |
||
| 9746 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9747 |
/// @solidity memory-safe-assembly |
||
| 9748 |
assembly {
|
||
| 9749 |
mstore(0x00, m0) |
||
| 9750 |
mstore(0x20, m1) |
||
| 9751 |
mstore(0x40, m2) |
||
| 9752 |
mstore(0x60, m3) |
||
| 9753 |
mstore(0x80, m4) |
||
| 9754 |
mstore(0xa0, m5) |
||
| 9755 |
mstore(0xc0, m6) |
||
| 9756 |
} |
||
| 9757 |
} |
||
| 9758 | |||
| 9759 |
function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure {
|
||
| 9760 |
bytes32 m0; |
||
| 9761 |
bytes32 m1; |
||
| 9762 |
bytes32 m2; |
||
| 9763 |
bytes32 m3; |
||
| 9764 |
bytes32 m4; |
||
| 9765 |
bytes32 m5; |
||
| 9766 |
bytes32 m6; |
||
| 9767 |
/// @solidity memory-safe-assembly |
||
| 9768 |
assembly {
|
||
| 9769 |
function writeString(pos, w) {
|
||
| 9770 |
let length := 0 |
||
| 9771 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9772 |
mstore(pos, length) |
||
| 9773 |
let shift := sub(256, shl(3, length)) |
||
| 9774 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9775 |
} |
||
| 9776 |
m0 := mload(0x00) |
||
| 9777 |
m1 := mload(0x20) |
||
| 9778 |
m2 := mload(0x40) |
||
| 9779 |
m3 := mload(0x60) |
||
| 9780 |
m4 := mload(0x80) |
||
| 9781 |
m5 := mload(0xa0) |
||
| 9782 |
m6 := mload(0xc0) |
||
| 9783 |
// Selector of `log(uint256,uint256,string,address)`. |
||
| 9784 |
mstore(0x00, 0x42d21db7) |
||
| 9785 |
mstore(0x20, p0) |
||
| 9786 |
mstore(0x40, p1) |
||
| 9787 |
mstore(0x60, 0x80) |
||
| 9788 |
mstore(0x80, p3) |
||
| 9789 |
writeString(0xa0, p2) |
||
| 9790 |
} |
||
| 9791 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9792 |
/// @solidity memory-safe-assembly |
||
| 9793 |
assembly {
|
||
| 9794 |
mstore(0x00, m0) |
||
| 9795 |
mstore(0x20, m1) |
||
| 9796 |
mstore(0x40, m2) |
||
| 9797 |
mstore(0x60, m3) |
||
| 9798 |
mstore(0x80, m4) |
||
| 9799 |
mstore(0xa0, m5) |
||
| 9800 |
mstore(0xc0, m6) |
||
| 9801 |
} |
||
| 9802 |
} |
||
| 9803 | |||
| 9804 |
function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
|
||
| 9805 |
bytes32 m0; |
||
| 9806 |
bytes32 m1; |
||
| 9807 |
bytes32 m2; |
||
| 9808 |
bytes32 m3; |
||
| 9809 |
bytes32 m4; |
||
| 9810 |
bytes32 m5; |
||
| 9811 |
bytes32 m6; |
||
| 9812 |
/// @solidity memory-safe-assembly |
||
| 9813 |
assembly {
|
||
| 9814 |
function writeString(pos, w) {
|
||
| 9815 |
let length := 0 |
||
| 9816 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9817 |
mstore(pos, length) |
||
| 9818 |
let shift := sub(256, shl(3, length)) |
||
| 9819 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9820 |
} |
||
| 9821 |
m0 := mload(0x00) |
||
| 9822 |
m1 := mload(0x20) |
||
| 9823 |
m2 := mload(0x40) |
||
| 9824 |
m3 := mload(0x60) |
||
| 9825 |
m4 := mload(0x80) |
||
| 9826 |
m5 := mload(0xa0) |
||
| 9827 |
m6 := mload(0xc0) |
||
| 9828 |
// Selector of `log(uint256,uint256,string,bool)`. |
||
| 9829 |
mstore(0x00, 0x7af6ab25) |
||
| 9830 |
mstore(0x20, p0) |
||
| 9831 |
mstore(0x40, p1) |
||
| 9832 |
mstore(0x60, 0x80) |
||
| 9833 |
mstore(0x80, p3) |
||
| 9834 |
writeString(0xa0, p2) |
||
| 9835 |
} |
||
| 9836 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9837 |
/// @solidity memory-safe-assembly |
||
| 9838 |
assembly {
|
||
| 9839 |
mstore(0x00, m0) |
||
| 9840 |
mstore(0x20, m1) |
||
| 9841 |
mstore(0x40, m2) |
||
| 9842 |
mstore(0x60, m3) |
||
| 9843 |
mstore(0x80, m4) |
||
| 9844 |
mstore(0xa0, m5) |
||
| 9845 |
mstore(0xc0, m6) |
||
| 9846 |
} |
||
| 9847 |
} |
||
| 9848 | |||
| 9849 |
function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 9850 |
bytes32 m0; |
||
| 9851 |
bytes32 m1; |
||
| 9852 |
bytes32 m2; |
||
| 9853 |
bytes32 m3; |
||
| 9854 |
bytes32 m4; |
||
| 9855 |
bytes32 m5; |
||
| 9856 |
bytes32 m6; |
||
| 9857 |
/// @solidity memory-safe-assembly |
||
| 9858 |
assembly {
|
||
| 9859 |
function writeString(pos, w) {
|
||
| 9860 |
let length := 0 |
||
| 9861 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9862 |
mstore(pos, length) |
||
| 9863 |
let shift := sub(256, shl(3, length)) |
||
| 9864 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9865 |
} |
||
| 9866 |
m0 := mload(0x00) |
||
| 9867 |
m1 := mload(0x20) |
||
| 9868 |
m2 := mload(0x40) |
||
| 9869 |
m3 := mload(0x60) |
||
| 9870 |
m4 := mload(0x80) |
||
| 9871 |
m5 := mload(0xa0) |
||
| 9872 |
m6 := mload(0xc0) |
||
| 9873 |
// Selector of `log(uint256,uint256,string,uint256)`. |
||
| 9874 |
mstore(0x00, 0x5da297eb) |
||
| 9875 |
mstore(0x20, p0) |
||
| 9876 |
mstore(0x40, p1) |
||
| 9877 |
mstore(0x60, 0x80) |
||
| 9878 |
mstore(0x80, p3) |
||
| 9879 |
writeString(0xa0, p2) |
||
| 9880 |
} |
||
| 9881 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9882 |
/// @solidity memory-safe-assembly |
||
| 9883 |
assembly {
|
||
| 9884 |
mstore(0x00, m0) |
||
| 9885 |
mstore(0x20, m1) |
||
| 9886 |
mstore(0x40, m2) |
||
| 9887 |
mstore(0x60, m3) |
||
| 9888 |
mstore(0x80, m4) |
||
| 9889 |
mstore(0xa0, m5) |
||
| 9890 |
mstore(0xc0, m6) |
||
| 9891 |
} |
||
| 9892 |
} |
||
| 9893 | |||
| 9894 |
function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 9895 |
bytes32 m0; |
||
| 9896 |
bytes32 m1; |
||
| 9897 |
bytes32 m2; |
||
| 9898 |
bytes32 m3; |
||
| 9899 |
bytes32 m4; |
||
| 9900 |
bytes32 m5; |
||
| 9901 |
bytes32 m6; |
||
| 9902 |
bytes32 m7; |
||
| 9903 |
bytes32 m8; |
||
| 9904 |
/// @solidity memory-safe-assembly |
||
| 9905 |
assembly {
|
||
| 9906 |
function writeString(pos, w) {
|
||
| 9907 |
let length := 0 |
||
| 9908 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9909 |
mstore(pos, length) |
||
| 9910 |
let shift := sub(256, shl(3, length)) |
||
| 9911 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9912 |
} |
||
| 9913 |
m0 := mload(0x00) |
||
| 9914 |
m1 := mload(0x20) |
||
| 9915 |
m2 := mload(0x40) |
||
| 9916 |
m3 := mload(0x60) |
||
| 9917 |
m4 := mload(0x80) |
||
| 9918 |
m5 := mload(0xa0) |
||
| 9919 |
m6 := mload(0xc0) |
||
| 9920 |
m7 := mload(0xe0) |
||
| 9921 |
m8 := mload(0x100) |
||
| 9922 |
// Selector of `log(uint256,uint256,string,string)`. |
||
| 9923 |
mstore(0x00, 0x27d8afd2) |
||
| 9924 |
mstore(0x20, p0) |
||
| 9925 |
mstore(0x40, p1) |
||
| 9926 |
mstore(0x60, 0x80) |
||
| 9927 |
mstore(0x80, 0xc0) |
||
| 9928 |
writeString(0xa0, p2) |
||
| 9929 |
writeString(0xe0, p3) |
||
| 9930 |
} |
||
| 9931 |
_sendLogPayload(0x1c, 0x104); |
||
| 9932 |
/// @solidity memory-safe-assembly |
||
| 9933 |
assembly {
|
||
| 9934 |
mstore(0x00, m0) |
||
| 9935 |
mstore(0x20, m1) |
||
| 9936 |
mstore(0x40, m2) |
||
| 9937 |
mstore(0x60, m3) |
||
| 9938 |
mstore(0x80, m4) |
||
| 9939 |
mstore(0xa0, m5) |
||
| 9940 |
mstore(0xc0, m6) |
||
| 9941 |
mstore(0xe0, m7) |
||
| 9942 |
mstore(0x100, m8) |
||
| 9943 |
} |
||
| 9944 |
} |
||
| 9945 | |||
| 9946 |
function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure {
|
||
| 9947 |
bytes32 m0; |
||
| 9948 |
bytes32 m1; |
||
| 9949 |
bytes32 m2; |
||
| 9950 |
bytes32 m3; |
||
| 9951 |
bytes32 m4; |
||
| 9952 |
bytes32 m5; |
||
| 9953 |
bytes32 m6; |
||
| 9954 |
/// @solidity memory-safe-assembly |
||
| 9955 |
assembly {
|
||
| 9956 |
function writeString(pos, w) {
|
||
| 9957 |
let length := 0 |
||
| 9958 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 9959 |
mstore(pos, length) |
||
| 9960 |
let shift := sub(256, shl(3, length)) |
||
| 9961 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 9962 |
} |
||
| 9963 |
m0 := mload(0x00) |
||
| 9964 |
m1 := mload(0x20) |
||
| 9965 |
m2 := mload(0x40) |
||
| 9966 |
m3 := mload(0x60) |
||
| 9967 |
m4 := mload(0x80) |
||
| 9968 |
m5 := mload(0xa0) |
||
| 9969 |
m6 := mload(0xc0) |
||
| 9970 |
// Selector of `log(uint256,string,address,address)`. |
||
| 9971 |
mstore(0x00, 0x6168ed61) |
||
| 9972 |
mstore(0x20, p0) |
||
| 9973 |
mstore(0x40, 0x80) |
||
| 9974 |
mstore(0x60, p2) |
||
| 9975 |
mstore(0x80, p3) |
||
| 9976 |
writeString(0xa0, p1) |
||
| 9977 |
} |
||
| 9978 |
_sendLogPayload(0x1c, 0xc4); |
||
| 9979 |
/// @solidity memory-safe-assembly |
||
| 9980 |
assembly {
|
||
| 9981 |
mstore(0x00, m0) |
||
| 9982 |
mstore(0x20, m1) |
||
| 9983 |
mstore(0x40, m2) |
||
| 9984 |
mstore(0x60, m3) |
||
| 9985 |
mstore(0x80, m4) |
||
| 9986 |
mstore(0xa0, m5) |
||
| 9987 |
mstore(0xc0, m6) |
||
| 9988 |
} |
||
| 9989 |
} |
||
| 9990 | |||
| 9991 |
function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure {
|
||
| 9992 |
bytes32 m0; |
||
| 9993 |
bytes32 m1; |
||
| 9994 |
bytes32 m2; |
||
| 9995 |
bytes32 m3; |
||
| 9996 |
bytes32 m4; |
||
| 9997 |
bytes32 m5; |
||
| 9998 |
bytes32 m6; |
||
| 9999 |
/// @solidity memory-safe-assembly |
||
| 10000 |
assembly {
|
||
| 10001 |
function writeString(pos, w) {
|
||
| 10002 |
let length := 0 |
||
| 10003 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10004 |
mstore(pos, length) |
||
| 10005 |
let shift := sub(256, shl(3, length)) |
||
| 10006 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10007 |
} |
||
| 10008 |
m0 := mload(0x00) |
||
| 10009 |
m1 := mload(0x20) |
||
| 10010 |
m2 := mload(0x40) |
||
| 10011 |
m3 := mload(0x60) |
||
| 10012 |
m4 := mload(0x80) |
||
| 10013 |
m5 := mload(0xa0) |
||
| 10014 |
m6 := mload(0xc0) |
||
| 10015 |
// Selector of `log(uint256,string,address,bool)`. |
||
| 10016 |
mstore(0x00, 0x90c30a56) |
||
| 10017 |
mstore(0x20, p0) |
||
| 10018 |
mstore(0x40, 0x80) |
||
| 10019 |
mstore(0x60, p2) |
||
| 10020 |
mstore(0x80, p3) |
||
| 10021 |
writeString(0xa0, p1) |
||
| 10022 |
} |
||
| 10023 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10024 |
/// @solidity memory-safe-assembly |
||
| 10025 |
assembly {
|
||
| 10026 |
mstore(0x00, m0) |
||
| 10027 |
mstore(0x20, m1) |
||
| 10028 |
mstore(0x40, m2) |
||
| 10029 |
mstore(0x60, m3) |
||
| 10030 |
mstore(0x80, m4) |
||
| 10031 |
mstore(0xa0, m5) |
||
| 10032 |
mstore(0xc0, m6) |
||
| 10033 |
} |
||
| 10034 |
} |
||
| 10035 | |||
| 10036 |
function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure {
|
||
| 10037 |
bytes32 m0; |
||
| 10038 |
bytes32 m1; |
||
| 10039 |
bytes32 m2; |
||
| 10040 |
bytes32 m3; |
||
| 10041 |
bytes32 m4; |
||
| 10042 |
bytes32 m5; |
||
| 10043 |
bytes32 m6; |
||
| 10044 |
/// @solidity memory-safe-assembly |
||
| 10045 |
assembly {
|
||
| 10046 |
function writeString(pos, w) {
|
||
| 10047 |
let length := 0 |
||
| 10048 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10049 |
mstore(pos, length) |
||
| 10050 |
let shift := sub(256, shl(3, length)) |
||
| 10051 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10052 |
} |
||
| 10053 |
m0 := mload(0x00) |
||
| 10054 |
m1 := mload(0x20) |
||
| 10055 |
m2 := mload(0x40) |
||
| 10056 |
m3 := mload(0x60) |
||
| 10057 |
m4 := mload(0x80) |
||
| 10058 |
m5 := mload(0xa0) |
||
| 10059 |
m6 := mload(0xc0) |
||
| 10060 |
// Selector of `log(uint256,string,address,uint256)`. |
||
| 10061 |
mstore(0x00, 0xe8d3018d) |
||
| 10062 |
mstore(0x20, p0) |
||
| 10063 |
mstore(0x40, 0x80) |
||
| 10064 |
mstore(0x60, p2) |
||
| 10065 |
mstore(0x80, p3) |
||
| 10066 |
writeString(0xa0, p1) |
||
| 10067 |
} |
||
| 10068 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10069 |
/// @solidity memory-safe-assembly |
||
| 10070 |
assembly {
|
||
| 10071 |
mstore(0x00, m0) |
||
| 10072 |
mstore(0x20, m1) |
||
| 10073 |
mstore(0x40, m2) |
||
| 10074 |
mstore(0x60, m3) |
||
| 10075 |
mstore(0x80, m4) |
||
| 10076 |
mstore(0xa0, m5) |
||
| 10077 |
mstore(0xc0, m6) |
||
| 10078 |
} |
||
| 10079 |
} |
||
| 10080 | |||
| 10081 |
function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
|
||
| 10082 |
bytes32 m0; |
||
| 10083 |
bytes32 m1; |
||
| 10084 |
bytes32 m2; |
||
| 10085 |
bytes32 m3; |
||
| 10086 |
bytes32 m4; |
||
| 10087 |
bytes32 m5; |
||
| 10088 |
bytes32 m6; |
||
| 10089 |
bytes32 m7; |
||
| 10090 |
bytes32 m8; |
||
| 10091 |
/// @solidity memory-safe-assembly |
||
| 10092 |
assembly {
|
||
| 10093 |
function writeString(pos, w) {
|
||
| 10094 |
let length := 0 |
||
| 10095 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10096 |
mstore(pos, length) |
||
| 10097 |
let shift := sub(256, shl(3, length)) |
||
| 10098 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10099 |
} |
||
| 10100 |
m0 := mload(0x00) |
||
| 10101 |
m1 := mload(0x20) |
||
| 10102 |
m2 := mload(0x40) |
||
| 10103 |
m3 := mload(0x60) |
||
| 10104 |
m4 := mload(0x80) |
||
| 10105 |
m5 := mload(0xa0) |
||
| 10106 |
m6 := mload(0xc0) |
||
| 10107 |
m7 := mload(0xe0) |
||
| 10108 |
m8 := mload(0x100) |
||
| 10109 |
// Selector of `log(uint256,string,address,string)`. |
||
| 10110 |
mstore(0x00, 0x9c3adfa1) |
||
| 10111 |
mstore(0x20, p0) |
||
| 10112 |
mstore(0x40, 0x80) |
||
| 10113 |
mstore(0x60, p2) |
||
| 10114 |
mstore(0x80, 0xc0) |
||
| 10115 |
writeString(0xa0, p1) |
||
| 10116 |
writeString(0xe0, p3) |
||
| 10117 |
} |
||
| 10118 |
_sendLogPayload(0x1c, 0x104); |
||
| 10119 |
/// @solidity memory-safe-assembly |
||
| 10120 |
assembly {
|
||
| 10121 |
mstore(0x00, m0) |
||
| 10122 |
mstore(0x20, m1) |
||
| 10123 |
mstore(0x40, m2) |
||
| 10124 |
mstore(0x60, m3) |
||
| 10125 |
mstore(0x80, m4) |
||
| 10126 |
mstore(0xa0, m5) |
||
| 10127 |
mstore(0xc0, m6) |
||
| 10128 |
mstore(0xe0, m7) |
||
| 10129 |
mstore(0x100, m8) |
||
| 10130 |
} |
||
| 10131 |
} |
||
| 10132 | |||
| 10133 |
function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure {
|
||
| 10134 |
bytes32 m0; |
||
| 10135 |
bytes32 m1; |
||
| 10136 |
bytes32 m2; |
||
| 10137 |
bytes32 m3; |
||
| 10138 |
bytes32 m4; |
||
| 10139 |
bytes32 m5; |
||
| 10140 |
bytes32 m6; |
||
| 10141 |
/// @solidity memory-safe-assembly |
||
| 10142 |
assembly {
|
||
| 10143 |
function writeString(pos, w) {
|
||
| 10144 |
let length := 0 |
||
| 10145 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10146 |
mstore(pos, length) |
||
| 10147 |
let shift := sub(256, shl(3, length)) |
||
| 10148 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10149 |
} |
||
| 10150 |
m0 := mload(0x00) |
||
| 10151 |
m1 := mload(0x20) |
||
| 10152 |
m2 := mload(0x40) |
||
| 10153 |
m3 := mload(0x60) |
||
| 10154 |
m4 := mload(0x80) |
||
| 10155 |
m5 := mload(0xa0) |
||
| 10156 |
m6 := mload(0xc0) |
||
| 10157 |
// Selector of `log(uint256,string,bool,address)`. |
||
| 10158 |
mstore(0x00, 0xae2ec581) |
||
| 10159 |
mstore(0x20, p0) |
||
| 10160 |
mstore(0x40, 0x80) |
||
| 10161 |
mstore(0x60, p2) |
||
| 10162 |
mstore(0x80, p3) |
||
| 10163 |
writeString(0xa0, p1) |
||
| 10164 |
} |
||
| 10165 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10166 |
/// @solidity memory-safe-assembly |
||
| 10167 |
assembly {
|
||
| 10168 |
mstore(0x00, m0) |
||
| 10169 |
mstore(0x20, m1) |
||
| 10170 |
mstore(0x40, m2) |
||
| 10171 |
mstore(0x60, m3) |
||
| 10172 |
mstore(0x80, m4) |
||
| 10173 |
mstore(0xa0, m5) |
||
| 10174 |
mstore(0xc0, m6) |
||
| 10175 |
} |
||
| 10176 |
} |
||
| 10177 | |||
| 10178 |
function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure {
|
||
| 10179 |
bytes32 m0; |
||
| 10180 |
bytes32 m1; |
||
| 10181 |
bytes32 m2; |
||
| 10182 |
bytes32 m3; |
||
| 10183 |
bytes32 m4; |
||
| 10184 |
bytes32 m5; |
||
| 10185 |
bytes32 m6; |
||
| 10186 |
/// @solidity memory-safe-assembly |
||
| 10187 |
assembly {
|
||
| 10188 |
function writeString(pos, w) {
|
||
| 10189 |
let length := 0 |
||
| 10190 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10191 |
mstore(pos, length) |
||
| 10192 |
let shift := sub(256, shl(3, length)) |
||
| 10193 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10194 |
} |
||
| 10195 |
m0 := mload(0x00) |
||
| 10196 |
m1 := mload(0x20) |
||
| 10197 |
m2 := mload(0x40) |
||
| 10198 |
m3 := mload(0x60) |
||
| 10199 |
m4 := mload(0x80) |
||
| 10200 |
m5 := mload(0xa0) |
||
| 10201 |
m6 := mload(0xc0) |
||
| 10202 |
// Selector of `log(uint256,string,bool,bool)`. |
||
| 10203 |
mstore(0x00, 0xba535d9c) |
||
| 10204 |
mstore(0x20, p0) |
||
| 10205 |
mstore(0x40, 0x80) |
||
| 10206 |
mstore(0x60, p2) |
||
| 10207 |
mstore(0x80, p3) |
||
| 10208 |
writeString(0xa0, p1) |
||
| 10209 |
} |
||
| 10210 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10211 |
/// @solidity memory-safe-assembly |
||
| 10212 |
assembly {
|
||
| 10213 |
mstore(0x00, m0) |
||
| 10214 |
mstore(0x20, m1) |
||
| 10215 |
mstore(0x40, m2) |
||
| 10216 |
mstore(0x60, m3) |
||
| 10217 |
mstore(0x80, m4) |
||
| 10218 |
mstore(0xa0, m5) |
||
| 10219 |
mstore(0xc0, m6) |
||
| 10220 |
} |
||
| 10221 |
} |
||
| 10222 | |||
| 10223 |
function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
|
||
| 10224 |
bytes32 m0; |
||
| 10225 |
bytes32 m1; |
||
| 10226 |
bytes32 m2; |
||
| 10227 |
bytes32 m3; |
||
| 10228 |
bytes32 m4; |
||
| 10229 |
bytes32 m5; |
||
| 10230 |
bytes32 m6; |
||
| 10231 |
/// @solidity memory-safe-assembly |
||
| 10232 |
assembly {
|
||
| 10233 |
function writeString(pos, w) {
|
||
| 10234 |
let length := 0 |
||
| 10235 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10236 |
mstore(pos, length) |
||
| 10237 |
let shift := sub(256, shl(3, length)) |
||
| 10238 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10239 |
} |
||
| 10240 |
m0 := mload(0x00) |
||
| 10241 |
m1 := mload(0x20) |
||
| 10242 |
m2 := mload(0x40) |
||
| 10243 |
m3 := mload(0x60) |
||
| 10244 |
m4 := mload(0x80) |
||
| 10245 |
m5 := mload(0xa0) |
||
| 10246 |
m6 := mload(0xc0) |
||
| 10247 |
// Selector of `log(uint256,string,bool,uint256)`. |
||
| 10248 |
mstore(0x00, 0xcf009880) |
||
| 10249 |
mstore(0x20, p0) |
||
| 10250 |
mstore(0x40, 0x80) |
||
| 10251 |
mstore(0x60, p2) |
||
| 10252 |
mstore(0x80, p3) |
||
| 10253 |
writeString(0xa0, p1) |
||
| 10254 |
} |
||
| 10255 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10256 |
/// @solidity memory-safe-assembly |
||
| 10257 |
assembly {
|
||
| 10258 |
mstore(0x00, m0) |
||
| 10259 |
mstore(0x20, m1) |
||
| 10260 |
mstore(0x40, m2) |
||
| 10261 |
mstore(0x60, m3) |
||
| 10262 |
mstore(0x80, m4) |
||
| 10263 |
mstore(0xa0, m5) |
||
| 10264 |
mstore(0xc0, m6) |
||
| 10265 |
} |
||
| 10266 |
} |
||
| 10267 | |||
| 10268 |
function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
|
||
| 10269 |
bytes32 m0; |
||
| 10270 |
bytes32 m1; |
||
| 10271 |
bytes32 m2; |
||
| 10272 |
bytes32 m3; |
||
| 10273 |
bytes32 m4; |
||
| 10274 |
bytes32 m5; |
||
| 10275 |
bytes32 m6; |
||
| 10276 |
bytes32 m7; |
||
| 10277 |
bytes32 m8; |
||
| 10278 |
/// @solidity memory-safe-assembly |
||
| 10279 |
assembly {
|
||
| 10280 |
function writeString(pos, w) {
|
||
| 10281 |
let length := 0 |
||
| 10282 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10283 |
mstore(pos, length) |
||
| 10284 |
let shift := sub(256, shl(3, length)) |
||
| 10285 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10286 |
} |
||
| 10287 |
m0 := mload(0x00) |
||
| 10288 |
m1 := mload(0x20) |
||
| 10289 |
m2 := mload(0x40) |
||
| 10290 |
m3 := mload(0x60) |
||
| 10291 |
m4 := mload(0x80) |
||
| 10292 |
m5 := mload(0xa0) |
||
| 10293 |
m6 := mload(0xc0) |
||
| 10294 |
m7 := mload(0xe0) |
||
| 10295 |
m8 := mload(0x100) |
||
| 10296 |
// Selector of `log(uint256,string,bool,string)`. |
||
| 10297 |
mstore(0x00, 0xd2d423cd) |
||
| 10298 |
mstore(0x20, p0) |
||
| 10299 |
mstore(0x40, 0x80) |
||
| 10300 |
mstore(0x60, p2) |
||
| 10301 |
mstore(0x80, 0xc0) |
||
| 10302 |
writeString(0xa0, p1) |
||
| 10303 |
writeString(0xe0, p3) |
||
| 10304 |
} |
||
| 10305 |
_sendLogPayload(0x1c, 0x104); |
||
| 10306 |
/// @solidity memory-safe-assembly |
||
| 10307 |
assembly {
|
||
| 10308 |
mstore(0x00, m0) |
||
| 10309 |
mstore(0x20, m1) |
||
| 10310 |
mstore(0x40, m2) |
||
| 10311 |
mstore(0x60, m3) |
||
| 10312 |
mstore(0x80, m4) |
||
| 10313 |
mstore(0xa0, m5) |
||
| 10314 |
mstore(0xc0, m6) |
||
| 10315 |
mstore(0xe0, m7) |
||
| 10316 |
mstore(0x100, m8) |
||
| 10317 |
} |
||
| 10318 |
} |
||
| 10319 | |||
| 10320 |
function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure {
|
||
| 10321 |
bytes32 m0; |
||
| 10322 |
bytes32 m1; |
||
| 10323 |
bytes32 m2; |
||
| 10324 |
bytes32 m3; |
||
| 10325 |
bytes32 m4; |
||
| 10326 |
bytes32 m5; |
||
| 10327 |
bytes32 m6; |
||
| 10328 |
/// @solidity memory-safe-assembly |
||
| 10329 |
assembly {
|
||
| 10330 |
function writeString(pos, w) {
|
||
| 10331 |
let length := 0 |
||
| 10332 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10333 |
mstore(pos, length) |
||
| 10334 |
let shift := sub(256, shl(3, length)) |
||
| 10335 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10336 |
} |
||
| 10337 |
m0 := mload(0x00) |
||
| 10338 |
m1 := mload(0x20) |
||
| 10339 |
m2 := mload(0x40) |
||
| 10340 |
m3 := mload(0x60) |
||
| 10341 |
m4 := mload(0x80) |
||
| 10342 |
m5 := mload(0xa0) |
||
| 10343 |
m6 := mload(0xc0) |
||
| 10344 |
// Selector of `log(uint256,string,uint256,address)`. |
||
| 10345 |
mstore(0x00, 0x3b2279b4) |
||
| 10346 |
mstore(0x20, p0) |
||
| 10347 |
mstore(0x40, 0x80) |
||
| 10348 |
mstore(0x60, p2) |
||
| 10349 |
mstore(0x80, p3) |
||
| 10350 |
writeString(0xa0, p1) |
||
| 10351 |
} |
||
| 10352 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10353 |
/// @solidity memory-safe-assembly |
||
| 10354 |
assembly {
|
||
| 10355 |
mstore(0x00, m0) |
||
| 10356 |
mstore(0x20, m1) |
||
| 10357 |
mstore(0x40, m2) |
||
| 10358 |
mstore(0x60, m3) |
||
| 10359 |
mstore(0x80, m4) |
||
| 10360 |
mstore(0xa0, m5) |
||
| 10361 |
mstore(0xc0, m6) |
||
| 10362 |
} |
||
| 10363 |
} |
||
| 10364 | |||
| 10365 |
function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
|
||
| 10366 |
bytes32 m0; |
||
| 10367 |
bytes32 m1; |
||
| 10368 |
bytes32 m2; |
||
| 10369 |
bytes32 m3; |
||
| 10370 |
bytes32 m4; |
||
| 10371 |
bytes32 m5; |
||
| 10372 |
bytes32 m6; |
||
| 10373 |
/// @solidity memory-safe-assembly |
||
| 10374 |
assembly {
|
||
| 10375 |
function writeString(pos, w) {
|
||
| 10376 |
let length := 0 |
||
| 10377 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10378 |
mstore(pos, length) |
||
| 10379 |
let shift := sub(256, shl(3, length)) |
||
| 10380 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10381 |
} |
||
| 10382 |
m0 := mload(0x00) |
||
| 10383 |
m1 := mload(0x20) |
||
| 10384 |
m2 := mload(0x40) |
||
| 10385 |
m3 := mload(0x60) |
||
| 10386 |
m4 := mload(0x80) |
||
| 10387 |
m5 := mload(0xa0) |
||
| 10388 |
m6 := mload(0xc0) |
||
| 10389 |
// Selector of `log(uint256,string,uint256,bool)`. |
||
| 10390 |
mstore(0x00, 0x691a8f74) |
||
| 10391 |
mstore(0x20, p0) |
||
| 10392 |
mstore(0x40, 0x80) |
||
| 10393 |
mstore(0x60, p2) |
||
| 10394 |
mstore(0x80, p3) |
||
| 10395 |
writeString(0xa0, p1) |
||
| 10396 |
} |
||
| 10397 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10398 |
/// @solidity memory-safe-assembly |
||
| 10399 |
assembly {
|
||
| 10400 |
mstore(0x00, m0) |
||
| 10401 |
mstore(0x20, m1) |
||
| 10402 |
mstore(0x40, m2) |
||
| 10403 |
mstore(0x60, m3) |
||
| 10404 |
mstore(0x80, m4) |
||
| 10405 |
mstore(0xa0, m5) |
||
| 10406 |
mstore(0xc0, m6) |
||
| 10407 |
} |
||
| 10408 |
} |
||
| 10409 | |||
| 10410 |
function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 10411 |
bytes32 m0; |
||
| 10412 |
bytes32 m1; |
||
| 10413 |
bytes32 m2; |
||
| 10414 |
bytes32 m3; |
||
| 10415 |
bytes32 m4; |
||
| 10416 |
bytes32 m5; |
||
| 10417 |
bytes32 m6; |
||
| 10418 |
/// @solidity memory-safe-assembly |
||
| 10419 |
assembly {
|
||
| 10420 |
function writeString(pos, w) {
|
||
| 10421 |
let length := 0 |
||
| 10422 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10423 |
mstore(pos, length) |
||
| 10424 |
let shift := sub(256, shl(3, length)) |
||
| 10425 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10426 |
} |
||
| 10427 |
m0 := mload(0x00) |
||
| 10428 |
m1 := mload(0x20) |
||
| 10429 |
m2 := mload(0x40) |
||
| 10430 |
m3 := mload(0x60) |
||
| 10431 |
m4 := mload(0x80) |
||
| 10432 |
m5 := mload(0xa0) |
||
| 10433 |
m6 := mload(0xc0) |
||
| 10434 |
// Selector of `log(uint256,string,uint256,uint256)`. |
||
| 10435 |
mstore(0x00, 0x82c25b74) |
||
| 10436 |
mstore(0x20, p0) |
||
| 10437 |
mstore(0x40, 0x80) |
||
| 10438 |
mstore(0x60, p2) |
||
| 10439 |
mstore(0x80, p3) |
||
| 10440 |
writeString(0xa0, p1) |
||
| 10441 |
} |
||
| 10442 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10443 |
/// @solidity memory-safe-assembly |
||
| 10444 |
assembly {
|
||
| 10445 |
mstore(0x00, m0) |
||
| 10446 |
mstore(0x20, m1) |
||
| 10447 |
mstore(0x40, m2) |
||
| 10448 |
mstore(0x60, m3) |
||
| 10449 |
mstore(0x80, m4) |
||
| 10450 |
mstore(0xa0, m5) |
||
| 10451 |
mstore(0xc0, m6) |
||
| 10452 |
} |
||
| 10453 |
} |
||
| 10454 | |||
| 10455 |
function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 10456 |
bytes32 m0; |
||
| 10457 |
bytes32 m1; |
||
| 10458 |
bytes32 m2; |
||
| 10459 |
bytes32 m3; |
||
| 10460 |
bytes32 m4; |
||
| 10461 |
bytes32 m5; |
||
| 10462 |
bytes32 m6; |
||
| 10463 |
bytes32 m7; |
||
| 10464 |
bytes32 m8; |
||
| 10465 |
/// @solidity memory-safe-assembly |
||
| 10466 |
assembly {
|
||
| 10467 |
function writeString(pos, w) {
|
||
| 10468 |
let length := 0 |
||
| 10469 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10470 |
mstore(pos, length) |
||
| 10471 |
let shift := sub(256, shl(3, length)) |
||
| 10472 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10473 |
} |
||
| 10474 |
m0 := mload(0x00) |
||
| 10475 |
m1 := mload(0x20) |
||
| 10476 |
m2 := mload(0x40) |
||
| 10477 |
m3 := mload(0x60) |
||
| 10478 |
m4 := mload(0x80) |
||
| 10479 |
m5 := mload(0xa0) |
||
| 10480 |
m6 := mload(0xc0) |
||
| 10481 |
m7 := mload(0xe0) |
||
| 10482 |
m8 := mload(0x100) |
||
| 10483 |
// Selector of `log(uint256,string,uint256,string)`. |
||
| 10484 |
mstore(0x00, 0xb7b914ca) |
||
| 10485 |
mstore(0x20, p0) |
||
| 10486 |
mstore(0x40, 0x80) |
||
| 10487 |
mstore(0x60, p2) |
||
| 10488 |
mstore(0x80, 0xc0) |
||
| 10489 |
writeString(0xa0, p1) |
||
| 10490 |
writeString(0xe0, p3) |
||
| 10491 |
} |
||
| 10492 |
_sendLogPayload(0x1c, 0x104); |
||
| 10493 |
/// @solidity memory-safe-assembly |
||
| 10494 |
assembly {
|
||
| 10495 |
mstore(0x00, m0) |
||
| 10496 |
mstore(0x20, m1) |
||
| 10497 |
mstore(0x40, m2) |
||
| 10498 |
mstore(0x60, m3) |
||
| 10499 |
mstore(0x80, m4) |
||
| 10500 |
mstore(0xa0, m5) |
||
| 10501 |
mstore(0xc0, m6) |
||
| 10502 |
mstore(0xe0, m7) |
||
| 10503 |
mstore(0x100, m8) |
||
| 10504 |
} |
||
| 10505 |
} |
||
| 10506 | |||
| 10507 |
function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
|
||
| 10508 |
bytes32 m0; |
||
| 10509 |
bytes32 m1; |
||
| 10510 |
bytes32 m2; |
||
| 10511 |
bytes32 m3; |
||
| 10512 |
bytes32 m4; |
||
| 10513 |
bytes32 m5; |
||
| 10514 |
bytes32 m6; |
||
| 10515 |
bytes32 m7; |
||
| 10516 |
bytes32 m8; |
||
| 10517 |
/// @solidity memory-safe-assembly |
||
| 10518 |
assembly {
|
||
| 10519 |
function writeString(pos, w) {
|
||
| 10520 |
let length := 0 |
||
| 10521 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10522 |
mstore(pos, length) |
||
| 10523 |
let shift := sub(256, shl(3, length)) |
||
| 10524 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10525 |
} |
||
| 10526 |
m0 := mload(0x00) |
||
| 10527 |
m1 := mload(0x20) |
||
| 10528 |
m2 := mload(0x40) |
||
| 10529 |
m3 := mload(0x60) |
||
| 10530 |
m4 := mload(0x80) |
||
| 10531 |
m5 := mload(0xa0) |
||
| 10532 |
m6 := mload(0xc0) |
||
| 10533 |
m7 := mload(0xe0) |
||
| 10534 |
m8 := mload(0x100) |
||
| 10535 |
// Selector of `log(uint256,string,string,address)`. |
||
| 10536 |
mstore(0x00, 0xd583c602) |
||
| 10537 |
mstore(0x20, p0) |
||
| 10538 |
mstore(0x40, 0x80) |
||
| 10539 |
mstore(0x60, 0xc0) |
||
| 10540 |
mstore(0x80, p3) |
||
| 10541 |
writeString(0xa0, p1) |
||
| 10542 |
writeString(0xe0, p2) |
||
| 10543 |
} |
||
| 10544 |
_sendLogPayload(0x1c, 0x104); |
||
| 10545 |
/// @solidity memory-safe-assembly |
||
| 10546 |
assembly {
|
||
| 10547 |
mstore(0x00, m0) |
||
| 10548 |
mstore(0x20, m1) |
||
| 10549 |
mstore(0x40, m2) |
||
| 10550 |
mstore(0x60, m3) |
||
| 10551 |
mstore(0x80, m4) |
||
| 10552 |
mstore(0xa0, m5) |
||
| 10553 |
mstore(0xc0, m6) |
||
| 10554 |
mstore(0xe0, m7) |
||
| 10555 |
mstore(0x100, m8) |
||
| 10556 |
} |
||
| 10557 |
} |
||
| 10558 | |||
| 10559 |
function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
|
||
| 10560 |
bytes32 m0; |
||
| 10561 |
bytes32 m1; |
||
| 10562 |
bytes32 m2; |
||
| 10563 |
bytes32 m3; |
||
| 10564 |
bytes32 m4; |
||
| 10565 |
bytes32 m5; |
||
| 10566 |
bytes32 m6; |
||
| 10567 |
bytes32 m7; |
||
| 10568 |
bytes32 m8; |
||
| 10569 |
/// @solidity memory-safe-assembly |
||
| 10570 |
assembly {
|
||
| 10571 |
function writeString(pos, w) {
|
||
| 10572 |
let length := 0 |
||
| 10573 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10574 |
mstore(pos, length) |
||
| 10575 |
let shift := sub(256, shl(3, length)) |
||
| 10576 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10577 |
} |
||
| 10578 |
m0 := mload(0x00) |
||
| 10579 |
m1 := mload(0x20) |
||
| 10580 |
m2 := mload(0x40) |
||
| 10581 |
m3 := mload(0x60) |
||
| 10582 |
m4 := mload(0x80) |
||
| 10583 |
m5 := mload(0xa0) |
||
| 10584 |
m6 := mload(0xc0) |
||
| 10585 |
m7 := mload(0xe0) |
||
| 10586 |
m8 := mload(0x100) |
||
| 10587 |
// Selector of `log(uint256,string,string,bool)`. |
||
| 10588 |
mstore(0x00, 0xb3a6b6bd) |
||
| 10589 |
mstore(0x20, p0) |
||
| 10590 |
mstore(0x40, 0x80) |
||
| 10591 |
mstore(0x60, 0xc0) |
||
| 10592 |
mstore(0x80, p3) |
||
| 10593 |
writeString(0xa0, p1) |
||
| 10594 |
writeString(0xe0, p2) |
||
| 10595 |
} |
||
| 10596 |
_sendLogPayload(0x1c, 0x104); |
||
| 10597 |
/// @solidity memory-safe-assembly |
||
| 10598 |
assembly {
|
||
| 10599 |
mstore(0x00, m0) |
||
| 10600 |
mstore(0x20, m1) |
||
| 10601 |
mstore(0x40, m2) |
||
| 10602 |
mstore(0x60, m3) |
||
| 10603 |
mstore(0x80, m4) |
||
| 10604 |
mstore(0xa0, m5) |
||
| 10605 |
mstore(0xc0, m6) |
||
| 10606 |
mstore(0xe0, m7) |
||
| 10607 |
mstore(0x100, m8) |
||
| 10608 |
} |
||
| 10609 |
} |
||
| 10610 | |||
| 10611 |
function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 10612 |
bytes32 m0; |
||
| 10613 |
bytes32 m1; |
||
| 10614 |
bytes32 m2; |
||
| 10615 |
bytes32 m3; |
||
| 10616 |
bytes32 m4; |
||
| 10617 |
bytes32 m5; |
||
| 10618 |
bytes32 m6; |
||
| 10619 |
bytes32 m7; |
||
| 10620 |
bytes32 m8; |
||
| 10621 |
/// @solidity memory-safe-assembly |
||
| 10622 |
assembly {
|
||
| 10623 |
function writeString(pos, w) {
|
||
| 10624 |
let length := 0 |
||
| 10625 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10626 |
mstore(pos, length) |
||
| 10627 |
let shift := sub(256, shl(3, length)) |
||
| 10628 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10629 |
} |
||
| 10630 |
m0 := mload(0x00) |
||
| 10631 |
m1 := mload(0x20) |
||
| 10632 |
m2 := mload(0x40) |
||
| 10633 |
m3 := mload(0x60) |
||
| 10634 |
m4 := mload(0x80) |
||
| 10635 |
m5 := mload(0xa0) |
||
| 10636 |
m6 := mload(0xc0) |
||
| 10637 |
m7 := mload(0xe0) |
||
| 10638 |
m8 := mload(0x100) |
||
| 10639 |
// Selector of `log(uint256,string,string,uint256)`. |
||
| 10640 |
mstore(0x00, 0xb028c9bd) |
||
| 10641 |
mstore(0x20, p0) |
||
| 10642 |
mstore(0x40, 0x80) |
||
| 10643 |
mstore(0x60, 0xc0) |
||
| 10644 |
mstore(0x80, p3) |
||
| 10645 |
writeString(0xa0, p1) |
||
| 10646 |
writeString(0xe0, p2) |
||
| 10647 |
} |
||
| 10648 |
_sendLogPayload(0x1c, 0x104); |
||
| 10649 |
/// @solidity memory-safe-assembly |
||
| 10650 |
assembly {
|
||
| 10651 |
mstore(0x00, m0) |
||
| 10652 |
mstore(0x20, m1) |
||
| 10653 |
mstore(0x40, m2) |
||
| 10654 |
mstore(0x60, m3) |
||
| 10655 |
mstore(0x80, m4) |
||
| 10656 |
mstore(0xa0, m5) |
||
| 10657 |
mstore(0xc0, m6) |
||
| 10658 |
mstore(0xe0, m7) |
||
| 10659 |
mstore(0x100, m8) |
||
| 10660 |
} |
||
| 10661 |
} |
||
| 10662 | |||
| 10663 |
function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 10664 |
bytes32 m0; |
||
| 10665 |
bytes32 m1; |
||
| 10666 |
bytes32 m2; |
||
| 10667 |
bytes32 m3; |
||
| 10668 |
bytes32 m4; |
||
| 10669 |
bytes32 m5; |
||
| 10670 |
bytes32 m6; |
||
| 10671 |
bytes32 m7; |
||
| 10672 |
bytes32 m8; |
||
| 10673 |
bytes32 m9; |
||
| 10674 |
bytes32 m10; |
||
| 10675 |
/// @solidity memory-safe-assembly |
||
| 10676 |
assembly {
|
||
| 10677 |
function writeString(pos, w) {
|
||
| 10678 |
let length := 0 |
||
| 10679 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10680 |
mstore(pos, length) |
||
| 10681 |
let shift := sub(256, shl(3, length)) |
||
| 10682 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10683 |
} |
||
| 10684 |
m0 := mload(0x00) |
||
| 10685 |
m1 := mload(0x20) |
||
| 10686 |
m2 := mload(0x40) |
||
| 10687 |
m3 := mload(0x60) |
||
| 10688 |
m4 := mload(0x80) |
||
| 10689 |
m5 := mload(0xa0) |
||
| 10690 |
m6 := mload(0xc0) |
||
| 10691 |
m7 := mload(0xe0) |
||
| 10692 |
m8 := mload(0x100) |
||
| 10693 |
m9 := mload(0x120) |
||
| 10694 |
m10 := mload(0x140) |
||
| 10695 |
// Selector of `log(uint256,string,string,string)`. |
||
| 10696 |
mstore(0x00, 0x21ad0683) |
||
| 10697 |
mstore(0x20, p0) |
||
| 10698 |
mstore(0x40, 0x80) |
||
| 10699 |
mstore(0x60, 0xc0) |
||
| 10700 |
mstore(0x80, 0x100) |
||
| 10701 |
writeString(0xa0, p1) |
||
| 10702 |
writeString(0xe0, p2) |
||
| 10703 |
writeString(0x120, p3) |
||
| 10704 |
} |
||
| 10705 |
_sendLogPayload(0x1c, 0x144); |
||
| 10706 |
/// @solidity memory-safe-assembly |
||
| 10707 |
assembly {
|
||
| 10708 |
mstore(0x00, m0) |
||
| 10709 |
mstore(0x20, m1) |
||
| 10710 |
mstore(0x40, m2) |
||
| 10711 |
mstore(0x60, m3) |
||
| 10712 |
mstore(0x80, m4) |
||
| 10713 |
mstore(0xa0, m5) |
||
| 10714 |
mstore(0xc0, m6) |
||
| 10715 |
mstore(0xe0, m7) |
||
| 10716 |
mstore(0x100, m8) |
||
| 10717 |
mstore(0x120, m9) |
||
| 10718 |
mstore(0x140, m10) |
||
| 10719 |
} |
||
| 10720 |
} |
||
| 10721 | |||
| 10722 |
function log(bytes32 p0, address p1, address p2, address p3) internal pure {
|
||
| 10723 |
bytes32 m0; |
||
| 10724 |
bytes32 m1; |
||
| 10725 |
bytes32 m2; |
||
| 10726 |
bytes32 m3; |
||
| 10727 |
bytes32 m4; |
||
| 10728 |
bytes32 m5; |
||
| 10729 |
bytes32 m6; |
||
| 10730 |
/// @solidity memory-safe-assembly |
||
| 10731 |
assembly {
|
||
| 10732 |
function writeString(pos, w) {
|
||
| 10733 |
let length := 0 |
||
| 10734 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10735 |
mstore(pos, length) |
||
| 10736 |
let shift := sub(256, shl(3, length)) |
||
| 10737 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10738 |
} |
||
| 10739 |
m0 := mload(0x00) |
||
| 10740 |
m1 := mload(0x20) |
||
| 10741 |
m2 := mload(0x40) |
||
| 10742 |
m3 := mload(0x60) |
||
| 10743 |
m4 := mload(0x80) |
||
| 10744 |
m5 := mload(0xa0) |
||
| 10745 |
m6 := mload(0xc0) |
||
| 10746 |
// Selector of `log(string,address,address,address)`. |
||
| 10747 |
mstore(0x00, 0xed8f28f6) |
||
| 10748 |
mstore(0x20, 0x80) |
||
| 10749 |
mstore(0x40, p1) |
||
| 10750 |
mstore(0x60, p2) |
||
| 10751 |
mstore(0x80, p3) |
||
| 10752 |
writeString(0xa0, p0) |
||
| 10753 |
} |
||
| 10754 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10755 |
/// @solidity memory-safe-assembly |
||
| 10756 |
assembly {
|
||
| 10757 |
mstore(0x00, m0) |
||
| 10758 |
mstore(0x20, m1) |
||
| 10759 |
mstore(0x40, m2) |
||
| 10760 |
mstore(0x60, m3) |
||
| 10761 |
mstore(0x80, m4) |
||
| 10762 |
mstore(0xa0, m5) |
||
| 10763 |
mstore(0xc0, m6) |
||
| 10764 |
} |
||
| 10765 |
} |
||
| 10766 | |||
| 10767 |
function log(bytes32 p0, address p1, address p2, bool p3) internal pure {
|
||
| 10768 |
bytes32 m0; |
||
| 10769 |
bytes32 m1; |
||
| 10770 |
bytes32 m2; |
||
| 10771 |
bytes32 m3; |
||
| 10772 |
bytes32 m4; |
||
| 10773 |
bytes32 m5; |
||
| 10774 |
bytes32 m6; |
||
| 10775 |
/// @solidity memory-safe-assembly |
||
| 10776 |
assembly {
|
||
| 10777 |
function writeString(pos, w) {
|
||
| 10778 |
let length := 0 |
||
| 10779 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10780 |
mstore(pos, length) |
||
| 10781 |
let shift := sub(256, shl(3, length)) |
||
| 10782 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10783 |
} |
||
| 10784 |
m0 := mload(0x00) |
||
| 10785 |
m1 := mload(0x20) |
||
| 10786 |
m2 := mload(0x40) |
||
| 10787 |
m3 := mload(0x60) |
||
| 10788 |
m4 := mload(0x80) |
||
| 10789 |
m5 := mload(0xa0) |
||
| 10790 |
m6 := mload(0xc0) |
||
| 10791 |
// Selector of `log(string,address,address,bool)`. |
||
| 10792 |
mstore(0x00, 0xb59dbd60) |
||
| 10793 |
mstore(0x20, 0x80) |
||
| 10794 |
mstore(0x40, p1) |
||
| 10795 |
mstore(0x60, p2) |
||
| 10796 |
mstore(0x80, p3) |
||
| 10797 |
writeString(0xa0, p0) |
||
| 10798 |
} |
||
| 10799 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10800 |
/// @solidity memory-safe-assembly |
||
| 10801 |
assembly {
|
||
| 10802 |
mstore(0x00, m0) |
||
| 10803 |
mstore(0x20, m1) |
||
| 10804 |
mstore(0x40, m2) |
||
| 10805 |
mstore(0x60, m3) |
||
| 10806 |
mstore(0x80, m4) |
||
| 10807 |
mstore(0xa0, m5) |
||
| 10808 |
mstore(0xc0, m6) |
||
| 10809 |
} |
||
| 10810 |
} |
||
| 10811 | |||
| 10812 |
function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure {
|
||
| 10813 |
bytes32 m0; |
||
| 10814 |
bytes32 m1; |
||
| 10815 |
bytes32 m2; |
||
| 10816 |
bytes32 m3; |
||
| 10817 |
bytes32 m4; |
||
| 10818 |
bytes32 m5; |
||
| 10819 |
bytes32 m6; |
||
| 10820 |
/// @solidity memory-safe-assembly |
||
| 10821 |
assembly {
|
||
| 10822 |
function writeString(pos, w) {
|
||
| 10823 |
let length := 0 |
||
| 10824 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10825 |
mstore(pos, length) |
||
| 10826 |
let shift := sub(256, shl(3, length)) |
||
| 10827 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10828 |
} |
||
| 10829 |
m0 := mload(0x00) |
||
| 10830 |
m1 := mload(0x20) |
||
| 10831 |
m2 := mload(0x40) |
||
| 10832 |
m3 := mload(0x60) |
||
| 10833 |
m4 := mload(0x80) |
||
| 10834 |
m5 := mload(0xa0) |
||
| 10835 |
m6 := mload(0xc0) |
||
| 10836 |
// Selector of `log(string,address,address,uint256)`. |
||
| 10837 |
mstore(0x00, 0x8ef3f399) |
||
| 10838 |
mstore(0x20, 0x80) |
||
| 10839 |
mstore(0x40, p1) |
||
| 10840 |
mstore(0x60, p2) |
||
| 10841 |
mstore(0x80, p3) |
||
| 10842 |
writeString(0xa0, p0) |
||
| 10843 |
} |
||
| 10844 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10845 |
/// @solidity memory-safe-assembly |
||
| 10846 |
assembly {
|
||
| 10847 |
mstore(0x00, m0) |
||
| 10848 |
mstore(0x20, m1) |
||
| 10849 |
mstore(0x40, m2) |
||
| 10850 |
mstore(0x60, m3) |
||
| 10851 |
mstore(0x80, m4) |
||
| 10852 |
mstore(0xa0, m5) |
||
| 10853 |
mstore(0xc0, m6) |
||
| 10854 |
} |
||
| 10855 |
} |
||
| 10856 | |||
| 10857 |
function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure {
|
||
| 10858 |
bytes32 m0; |
||
| 10859 |
bytes32 m1; |
||
| 10860 |
bytes32 m2; |
||
| 10861 |
bytes32 m3; |
||
| 10862 |
bytes32 m4; |
||
| 10863 |
bytes32 m5; |
||
| 10864 |
bytes32 m6; |
||
| 10865 |
bytes32 m7; |
||
| 10866 |
bytes32 m8; |
||
| 10867 |
/// @solidity memory-safe-assembly |
||
| 10868 |
assembly {
|
||
| 10869 |
function writeString(pos, w) {
|
||
| 10870 |
let length := 0 |
||
| 10871 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10872 |
mstore(pos, length) |
||
| 10873 |
let shift := sub(256, shl(3, length)) |
||
| 10874 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10875 |
} |
||
| 10876 |
m0 := mload(0x00) |
||
| 10877 |
m1 := mload(0x20) |
||
| 10878 |
m2 := mload(0x40) |
||
| 10879 |
m3 := mload(0x60) |
||
| 10880 |
m4 := mload(0x80) |
||
| 10881 |
m5 := mload(0xa0) |
||
| 10882 |
m6 := mload(0xc0) |
||
| 10883 |
m7 := mload(0xe0) |
||
| 10884 |
m8 := mload(0x100) |
||
| 10885 |
// Selector of `log(string,address,address,string)`. |
||
| 10886 |
mstore(0x00, 0x800a1c67) |
||
| 10887 |
mstore(0x20, 0x80) |
||
| 10888 |
mstore(0x40, p1) |
||
| 10889 |
mstore(0x60, p2) |
||
| 10890 |
mstore(0x80, 0xc0) |
||
| 10891 |
writeString(0xa0, p0) |
||
| 10892 |
writeString(0xe0, p3) |
||
| 10893 |
} |
||
| 10894 |
_sendLogPayload(0x1c, 0x104); |
||
| 10895 |
/// @solidity memory-safe-assembly |
||
| 10896 |
assembly {
|
||
| 10897 |
mstore(0x00, m0) |
||
| 10898 |
mstore(0x20, m1) |
||
| 10899 |
mstore(0x40, m2) |
||
| 10900 |
mstore(0x60, m3) |
||
| 10901 |
mstore(0x80, m4) |
||
| 10902 |
mstore(0xa0, m5) |
||
| 10903 |
mstore(0xc0, m6) |
||
| 10904 |
mstore(0xe0, m7) |
||
| 10905 |
mstore(0x100, m8) |
||
| 10906 |
} |
||
| 10907 |
} |
||
| 10908 | |||
| 10909 |
function log(bytes32 p0, address p1, bool p2, address p3) internal pure {
|
||
| 10910 |
bytes32 m0; |
||
| 10911 |
bytes32 m1; |
||
| 10912 |
bytes32 m2; |
||
| 10913 |
bytes32 m3; |
||
| 10914 |
bytes32 m4; |
||
| 10915 |
bytes32 m5; |
||
| 10916 |
bytes32 m6; |
||
| 10917 |
/// @solidity memory-safe-assembly |
||
| 10918 |
assembly {
|
||
| 10919 |
function writeString(pos, w) {
|
||
| 10920 |
let length := 0 |
||
| 10921 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10922 |
mstore(pos, length) |
||
| 10923 |
let shift := sub(256, shl(3, length)) |
||
| 10924 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10925 |
} |
||
| 10926 |
m0 := mload(0x00) |
||
| 10927 |
m1 := mload(0x20) |
||
| 10928 |
m2 := mload(0x40) |
||
| 10929 |
m3 := mload(0x60) |
||
| 10930 |
m4 := mload(0x80) |
||
| 10931 |
m5 := mload(0xa0) |
||
| 10932 |
m6 := mload(0xc0) |
||
| 10933 |
// Selector of `log(string,address,bool,address)`. |
||
| 10934 |
mstore(0x00, 0x223603bd) |
||
| 10935 |
mstore(0x20, 0x80) |
||
| 10936 |
mstore(0x40, p1) |
||
| 10937 |
mstore(0x60, p2) |
||
| 10938 |
mstore(0x80, p3) |
||
| 10939 |
writeString(0xa0, p0) |
||
| 10940 |
} |
||
| 10941 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10942 |
/// @solidity memory-safe-assembly |
||
| 10943 |
assembly {
|
||
| 10944 |
mstore(0x00, m0) |
||
| 10945 |
mstore(0x20, m1) |
||
| 10946 |
mstore(0x40, m2) |
||
| 10947 |
mstore(0x60, m3) |
||
| 10948 |
mstore(0x80, m4) |
||
| 10949 |
mstore(0xa0, m5) |
||
| 10950 |
mstore(0xc0, m6) |
||
| 10951 |
} |
||
| 10952 |
} |
||
| 10953 | |||
| 10954 |
function log(bytes32 p0, address p1, bool p2, bool p3) internal pure {
|
||
| 10955 |
bytes32 m0; |
||
| 10956 |
bytes32 m1; |
||
| 10957 |
bytes32 m2; |
||
| 10958 |
bytes32 m3; |
||
| 10959 |
bytes32 m4; |
||
| 10960 |
bytes32 m5; |
||
| 10961 |
bytes32 m6; |
||
| 10962 |
/// @solidity memory-safe-assembly |
||
| 10963 |
assembly {
|
||
| 10964 |
function writeString(pos, w) {
|
||
| 10965 |
let length := 0 |
||
| 10966 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 10967 |
mstore(pos, length) |
||
| 10968 |
let shift := sub(256, shl(3, length)) |
||
| 10969 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 10970 |
} |
||
| 10971 |
m0 := mload(0x00) |
||
| 10972 |
m1 := mload(0x20) |
||
| 10973 |
m2 := mload(0x40) |
||
| 10974 |
m3 := mload(0x60) |
||
| 10975 |
m4 := mload(0x80) |
||
| 10976 |
m5 := mload(0xa0) |
||
| 10977 |
m6 := mload(0xc0) |
||
| 10978 |
// Selector of `log(string,address,bool,bool)`. |
||
| 10979 |
mstore(0x00, 0x79884c2b) |
||
| 10980 |
mstore(0x20, 0x80) |
||
| 10981 |
mstore(0x40, p1) |
||
| 10982 |
mstore(0x60, p2) |
||
| 10983 |
mstore(0x80, p3) |
||
| 10984 |
writeString(0xa0, p0) |
||
| 10985 |
} |
||
| 10986 |
_sendLogPayload(0x1c, 0xc4); |
||
| 10987 |
/// @solidity memory-safe-assembly |
||
| 10988 |
assembly {
|
||
| 10989 |
mstore(0x00, m0) |
||
| 10990 |
mstore(0x20, m1) |
||
| 10991 |
mstore(0x40, m2) |
||
| 10992 |
mstore(0x60, m3) |
||
| 10993 |
mstore(0x80, m4) |
||
| 10994 |
mstore(0xa0, m5) |
||
| 10995 |
mstore(0xc0, m6) |
||
| 10996 |
} |
||
| 10997 |
} |
||
| 10998 | |||
| 10999 |
function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure {
|
||
| 11000 |
bytes32 m0; |
||
| 11001 |
bytes32 m1; |
||
| 11002 |
bytes32 m2; |
||
| 11003 |
bytes32 m3; |
||
| 11004 |
bytes32 m4; |
||
| 11005 |
bytes32 m5; |
||
| 11006 |
bytes32 m6; |
||
| 11007 |
/// @solidity memory-safe-assembly |
||
| 11008 |
assembly {
|
||
| 11009 |
function writeString(pos, w) {
|
||
| 11010 |
let length := 0 |
||
| 11011 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11012 |
mstore(pos, length) |
||
| 11013 |
let shift := sub(256, shl(3, length)) |
||
| 11014 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11015 |
} |
||
| 11016 |
m0 := mload(0x00) |
||
| 11017 |
m1 := mload(0x20) |
||
| 11018 |
m2 := mload(0x40) |
||
| 11019 |
m3 := mload(0x60) |
||
| 11020 |
m4 := mload(0x80) |
||
| 11021 |
m5 := mload(0xa0) |
||
| 11022 |
m6 := mload(0xc0) |
||
| 11023 |
// Selector of `log(string,address,bool,uint256)`. |
||
| 11024 |
mstore(0x00, 0x3e9f866a) |
||
| 11025 |
mstore(0x20, 0x80) |
||
| 11026 |
mstore(0x40, p1) |
||
| 11027 |
mstore(0x60, p2) |
||
| 11028 |
mstore(0x80, p3) |
||
| 11029 |
writeString(0xa0, p0) |
||
| 11030 |
} |
||
| 11031 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11032 |
/// @solidity memory-safe-assembly |
||
| 11033 |
assembly {
|
||
| 11034 |
mstore(0x00, m0) |
||
| 11035 |
mstore(0x20, m1) |
||
| 11036 |
mstore(0x40, m2) |
||
| 11037 |
mstore(0x60, m3) |
||
| 11038 |
mstore(0x80, m4) |
||
| 11039 |
mstore(0xa0, m5) |
||
| 11040 |
mstore(0xc0, m6) |
||
| 11041 |
} |
||
| 11042 |
} |
||
| 11043 | |||
| 11044 |
function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure {
|
||
| 11045 |
bytes32 m0; |
||
| 11046 |
bytes32 m1; |
||
| 11047 |
bytes32 m2; |
||
| 11048 |
bytes32 m3; |
||
| 11049 |
bytes32 m4; |
||
| 11050 |
bytes32 m5; |
||
| 11051 |
bytes32 m6; |
||
| 11052 |
bytes32 m7; |
||
| 11053 |
bytes32 m8; |
||
| 11054 |
/// @solidity memory-safe-assembly |
||
| 11055 |
assembly {
|
||
| 11056 |
function writeString(pos, w) {
|
||
| 11057 |
let length := 0 |
||
| 11058 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11059 |
mstore(pos, length) |
||
| 11060 |
let shift := sub(256, shl(3, length)) |
||
| 11061 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11062 |
} |
||
| 11063 |
m0 := mload(0x00) |
||
| 11064 |
m1 := mload(0x20) |
||
| 11065 |
m2 := mload(0x40) |
||
| 11066 |
m3 := mload(0x60) |
||
| 11067 |
m4 := mload(0x80) |
||
| 11068 |
m5 := mload(0xa0) |
||
| 11069 |
m6 := mload(0xc0) |
||
| 11070 |
m7 := mload(0xe0) |
||
| 11071 |
m8 := mload(0x100) |
||
| 11072 |
// Selector of `log(string,address,bool,string)`. |
||
| 11073 |
mstore(0x00, 0x0454c079) |
||
| 11074 |
mstore(0x20, 0x80) |
||
| 11075 |
mstore(0x40, p1) |
||
| 11076 |
mstore(0x60, p2) |
||
| 11077 |
mstore(0x80, 0xc0) |
||
| 11078 |
writeString(0xa0, p0) |
||
| 11079 |
writeString(0xe0, p3) |
||
| 11080 |
} |
||
| 11081 |
_sendLogPayload(0x1c, 0x104); |
||
| 11082 |
/// @solidity memory-safe-assembly |
||
| 11083 |
assembly {
|
||
| 11084 |
mstore(0x00, m0) |
||
| 11085 |
mstore(0x20, m1) |
||
| 11086 |
mstore(0x40, m2) |
||
| 11087 |
mstore(0x60, m3) |
||
| 11088 |
mstore(0x80, m4) |
||
| 11089 |
mstore(0xa0, m5) |
||
| 11090 |
mstore(0xc0, m6) |
||
| 11091 |
mstore(0xe0, m7) |
||
| 11092 |
mstore(0x100, m8) |
||
| 11093 |
} |
||
| 11094 |
} |
||
| 11095 | |||
| 11096 |
function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure {
|
||
| 11097 |
bytes32 m0; |
||
| 11098 |
bytes32 m1; |
||
| 11099 |
bytes32 m2; |
||
| 11100 |
bytes32 m3; |
||
| 11101 |
bytes32 m4; |
||
| 11102 |
bytes32 m5; |
||
| 11103 |
bytes32 m6; |
||
| 11104 |
/// @solidity memory-safe-assembly |
||
| 11105 |
assembly {
|
||
| 11106 |
function writeString(pos, w) {
|
||
| 11107 |
let length := 0 |
||
| 11108 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11109 |
mstore(pos, length) |
||
| 11110 |
let shift := sub(256, shl(3, length)) |
||
| 11111 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11112 |
} |
||
| 11113 |
m0 := mload(0x00) |
||
| 11114 |
m1 := mload(0x20) |
||
| 11115 |
m2 := mload(0x40) |
||
| 11116 |
m3 := mload(0x60) |
||
| 11117 |
m4 := mload(0x80) |
||
| 11118 |
m5 := mload(0xa0) |
||
| 11119 |
m6 := mload(0xc0) |
||
| 11120 |
// Selector of `log(string,address,uint256,address)`. |
||
| 11121 |
mstore(0x00, 0x63fb8bc5) |
||
| 11122 |
mstore(0x20, 0x80) |
||
| 11123 |
mstore(0x40, p1) |
||
| 11124 |
mstore(0x60, p2) |
||
| 11125 |
mstore(0x80, p3) |
||
| 11126 |
writeString(0xa0, p0) |
||
| 11127 |
} |
||
| 11128 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11129 |
/// @solidity memory-safe-assembly |
||
| 11130 |
assembly {
|
||
| 11131 |
mstore(0x00, m0) |
||
| 11132 |
mstore(0x20, m1) |
||
| 11133 |
mstore(0x40, m2) |
||
| 11134 |
mstore(0x60, m3) |
||
| 11135 |
mstore(0x80, m4) |
||
| 11136 |
mstore(0xa0, m5) |
||
| 11137 |
mstore(0xc0, m6) |
||
| 11138 |
} |
||
| 11139 |
} |
||
| 11140 | |||
| 11141 |
function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure {
|
||
| 11142 |
bytes32 m0; |
||
| 11143 |
bytes32 m1; |
||
| 11144 |
bytes32 m2; |
||
| 11145 |
bytes32 m3; |
||
| 11146 |
bytes32 m4; |
||
| 11147 |
bytes32 m5; |
||
| 11148 |
bytes32 m6; |
||
| 11149 |
/// @solidity memory-safe-assembly |
||
| 11150 |
assembly {
|
||
| 11151 |
function writeString(pos, w) {
|
||
| 11152 |
let length := 0 |
||
| 11153 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11154 |
mstore(pos, length) |
||
| 11155 |
let shift := sub(256, shl(3, length)) |
||
| 11156 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11157 |
} |
||
| 11158 |
m0 := mload(0x00) |
||
| 11159 |
m1 := mload(0x20) |
||
| 11160 |
m2 := mload(0x40) |
||
| 11161 |
m3 := mload(0x60) |
||
| 11162 |
m4 := mload(0x80) |
||
| 11163 |
m5 := mload(0xa0) |
||
| 11164 |
m6 := mload(0xc0) |
||
| 11165 |
// Selector of `log(string,address,uint256,bool)`. |
||
| 11166 |
mstore(0x00, 0xfc4845f0) |
||
| 11167 |
mstore(0x20, 0x80) |
||
| 11168 |
mstore(0x40, p1) |
||
| 11169 |
mstore(0x60, p2) |
||
| 11170 |
mstore(0x80, p3) |
||
| 11171 |
writeString(0xa0, p0) |
||
| 11172 |
} |
||
| 11173 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11174 |
/// @solidity memory-safe-assembly |
||
| 11175 |
assembly {
|
||
| 11176 |
mstore(0x00, m0) |
||
| 11177 |
mstore(0x20, m1) |
||
| 11178 |
mstore(0x40, m2) |
||
| 11179 |
mstore(0x60, m3) |
||
| 11180 |
mstore(0x80, m4) |
||
| 11181 |
mstore(0xa0, m5) |
||
| 11182 |
mstore(0xc0, m6) |
||
| 11183 |
} |
||
| 11184 |
} |
||
| 11185 | |||
| 11186 |
function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure {
|
||
| 11187 |
bytes32 m0; |
||
| 11188 |
bytes32 m1; |
||
| 11189 |
bytes32 m2; |
||
| 11190 |
bytes32 m3; |
||
| 11191 |
bytes32 m4; |
||
| 11192 |
bytes32 m5; |
||
| 11193 |
bytes32 m6; |
||
| 11194 |
/// @solidity memory-safe-assembly |
||
| 11195 |
assembly {
|
||
| 11196 |
function writeString(pos, w) {
|
||
| 11197 |
let length := 0 |
||
| 11198 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11199 |
mstore(pos, length) |
||
| 11200 |
let shift := sub(256, shl(3, length)) |
||
| 11201 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11202 |
} |
||
| 11203 |
m0 := mload(0x00) |
||
| 11204 |
m1 := mload(0x20) |
||
| 11205 |
m2 := mload(0x40) |
||
| 11206 |
m3 := mload(0x60) |
||
| 11207 |
m4 := mload(0x80) |
||
| 11208 |
m5 := mload(0xa0) |
||
| 11209 |
m6 := mload(0xc0) |
||
| 11210 |
// Selector of `log(string,address,uint256,uint256)`. |
||
| 11211 |
mstore(0x00, 0xf8f51b1e) |
||
| 11212 |
mstore(0x20, 0x80) |
||
| 11213 |
mstore(0x40, p1) |
||
| 11214 |
mstore(0x60, p2) |
||
| 11215 |
mstore(0x80, p3) |
||
| 11216 |
writeString(0xa0, p0) |
||
| 11217 |
} |
||
| 11218 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11219 |
/// @solidity memory-safe-assembly |
||
| 11220 |
assembly {
|
||
| 11221 |
mstore(0x00, m0) |
||
| 11222 |
mstore(0x20, m1) |
||
| 11223 |
mstore(0x40, m2) |
||
| 11224 |
mstore(0x60, m3) |
||
| 11225 |
mstore(0x80, m4) |
||
| 11226 |
mstore(0xa0, m5) |
||
| 11227 |
mstore(0xc0, m6) |
||
| 11228 |
} |
||
| 11229 |
} |
||
| 11230 | |||
| 11231 |
function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 11232 |
bytes32 m0; |
||
| 11233 |
bytes32 m1; |
||
| 11234 |
bytes32 m2; |
||
| 11235 |
bytes32 m3; |
||
| 11236 |
bytes32 m4; |
||
| 11237 |
bytes32 m5; |
||
| 11238 |
bytes32 m6; |
||
| 11239 |
bytes32 m7; |
||
| 11240 |
bytes32 m8; |
||
| 11241 |
/// @solidity memory-safe-assembly |
||
| 11242 |
assembly {
|
||
| 11243 |
function writeString(pos, w) {
|
||
| 11244 |
let length := 0 |
||
| 11245 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11246 |
mstore(pos, length) |
||
| 11247 |
let shift := sub(256, shl(3, length)) |
||
| 11248 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11249 |
} |
||
| 11250 |
m0 := mload(0x00) |
||
| 11251 |
m1 := mload(0x20) |
||
| 11252 |
m2 := mload(0x40) |
||
| 11253 |
m3 := mload(0x60) |
||
| 11254 |
m4 := mload(0x80) |
||
| 11255 |
m5 := mload(0xa0) |
||
| 11256 |
m6 := mload(0xc0) |
||
| 11257 |
m7 := mload(0xe0) |
||
| 11258 |
m8 := mload(0x100) |
||
| 11259 |
// Selector of `log(string,address,uint256,string)`. |
||
| 11260 |
mstore(0x00, 0x5a477632) |
||
| 11261 |
mstore(0x20, 0x80) |
||
| 11262 |
mstore(0x40, p1) |
||
| 11263 |
mstore(0x60, p2) |
||
| 11264 |
mstore(0x80, 0xc0) |
||
| 11265 |
writeString(0xa0, p0) |
||
| 11266 |
writeString(0xe0, p3) |
||
| 11267 |
} |
||
| 11268 |
_sendLogPayload(0x1c, 0x104); |
||
| 11269 |
/// @solidity memory-safe-assembly |
||
| 11270 |
assembly {
|
||
| 11271 |
mstore(0x00, m0) |
||
| 11272 |
mstore(0x20, m1) |
||
| 11273 |
mstore(0x40, m2) |
||
| 11274 |
mstore(0x60, m3) |
||
| 11275 |
mstore(0x80, m4) |
||
| 11276 |
mstore(0xa0, m5) |
||
| 11277 |
mstore(0xc0, m6) |
||
| 11278 |
mstore(0xe0, m7) |
||
| 11279 |
mstore(0x100, m8) |
||
| 11280 |
} |
||
| 11281 |
} |
||
| 11282 | |||
| 11283 |
function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure {
|
||
| 11284 |
bytes32 m0; |
||
| 11285 |
bytes32 m1; |
||
| 11286 |
bytes32 m2; |
||
| 11287 |
bytes32 m3; |
||
| 11288 |
bytes32 m4; |
||
| 11289 |
bytes32 m5; |
||
| 11290 |
bytes32 m6; |
||
| 11291 |
bytes32 m7; |
||
| 11292 |
bytes32 m8; |
||
| 11293 |
/// @solidity memory-safe-assembly |
||
| 11294 |
assembly {
|
||
| 11295 |
function writeString(pos, w) {
|
||
| 11296 |
let length := 0 |
||
| 11297 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11298 |
mstore(pos, length) |
||
| 11299 |
let shift := sub(256, shl(3, length)) |
||
| 11300 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11301 |
} |
||
| 11302 |
m0 := mload(0x00) |
||
| 11303 |
m1 := mload(0x20) |
||
| 11304 |
m2 := mload(0x40) |
||
| 11305 |
m3 := mload(0x60) |
||
| 11306 |
m4 := mload(0x80) |
||
| 11307 |
m5 := mload(0xa0) |
||
| 11308 |
m6 := mload(0xc0) |
||
| 11309 |
m7 := mload(0xe0) |
||
| 11310 |
m8 := mload(0x100) |
||
| 11311 |
// Selector of `log(string,address,string,address)`. |
||
| 11312 |
mstore(0x00, 0xaabc9a31) |
||
| 11313 |
mstore(0x20, 0x80) |
||
| 11314 |
mstore(0x40, p1) |
||
| 11315 |
mstore(0x60, 0xc0) |
||
| 11316 |
mstore(0x80, p3) |
||
| 11317 |
writeString(0xa0, p0) |
||
| 11318 |
writeString(0xe0, p2) |
||
| 11319 |
} |
||
| 11320 |
_sendLogPayload(0x1c, 0x104); |
||
| 11321 |
/// @solidity memory-safe-assembly |
||
| 11322 |
assembly {
|
||
| 11323 |
mstore(0x00, m0) |
||
| 11324 |
mstore(0x20, m1) |
||
| 11325 |
mstore(0x40, m2) |
||
| 11326 |
mstore(0x60, m3) |
||
| 11327 |
mstore(0x80, m4) |
||
| 11328 |
mstore(0xa0, m5) |
||
| 11329 |
mstore(0xc0, m6) |
||
| 11330 |
mstore(0xe0, m7) |
||
| 11331 |
mstore(0x100, m8) |
||
| 11332 |
} |
||
| 11333 |
} |
||
| 11334 | |||
| 11335 |
function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure {
|
||
| 11336 |
bytes32 m0; |
||
| 11337 |
bytes32 m1; |
||
| 11338 |
bytes32 m2; |
||
| 11339 |
bytes32 m3; |
||
| 11340 |
bytes32 m4; |
||
| 11341 |
bytes32 m5; |
||
| 11342 |
bytes32 m6; |
||
| 11343 |
bytes32 m7; |
||
| 11344 |
bytes32 m8; |
||
| 11345 |
/// @solidity memory-safe-assembly |
||
| 11346 |
assembly {
|
||
| 11347 |
function writeString(pos, w) {
|
||
| 11348 |
let length := 0 |
||
| 11349 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11350 |
mstore(pos, length) |
||
| 11351 |
let shift := sub(256, shl(3, length)) |
||
| 11352 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11353 |
} |
||
| 11354 |
m0 := mload(0x00) |
||
| 11355 |
m1 := mload(0x20) |
||
| 11356 |
m2 := mload(0x40) |
||
| 11357 |
m3 := mload(0x60) |
||
| 11358 |
m4 := mload(0x80) |
||
| 11359 |
m5 := mload(0xa0) |
||
| 11360 |
m6 := mload(0xc0) |
||
| 11361 |
m7 := mload(0xe0) |
||
| 11362 |
m8 := mload(0x100) |
||
| 11363 |
// Selector of `log(string,address,string,bool)`. |
||
| 11364 |
mstore(0x00, 0x5f15d28c) |
||
| 11365 |
mstore(0x20, 0x80) |
||
| 11366 |
mstore(0x40, p1) |
||
| 11367 |
mstore(0x60, 0xc0) |
||
| 11368 |
mstore(0x80, p3) |
||
| 11369 |
writeString(0xa0, p0) |
||
| 11370 |
writeString(0xe0, p2) |
||
| 11371 |
} |
||
| 11372 |
_sendLogPayload(0x1c, 0x104); |
||
| 11373 |
/// @solidity memory-safe-assembly |
||
| 11374 |
assembly {
|
||
| 11375 |
mstore(0x00, m0) |
||
| 11376 |
mstore(0x20, m1) |
||
| 11377 |
mstore(0x40, m2) |
||
| 11378 |
mstore(0x60, m3) |
||
| 11379 |
mstore(0x80, m4) |
||
| 11380 |
mstore(0xa0, m5) |
||
| 11381 |
mstore(0xc0, m6) |
||
| 11382 |
mstore(0xe0, m7) |
||
| 11383 |
mstore(0x100, m8) |
||
| 11384 |
} |
||
| 11385 |
} |
||
| 11386 | |||
| 11387 |
function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 11388 |
bytes32 m0; |
||
| 11389 |
bytes32 m1; |
||
| 11390 |
bytes32 m2; |
||
| 11391 |
bytes32 m3; |
||
| 11392 |
bytes32 m4; |
||
| 11393 |
bytes32 m5; |
||
| 11394 |
bytes32 m6; |
||
| 11395 |
bytes32 m7; |
||
| 11396 |
bytes32 m8; |
||
| 11397 |
/// @solidity memory-safe-assembly |
||
| 11398 |
assembly {
|
||
| 11399 |
function writeString(pos, w) {
|
||
| 11400 |
let length := 0 |
||
| 11401 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11402 |
mstore(pos, length) |
||
| 11403 |
let shift := sub(256, shl(3, length)) |
||
| 11404 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11405 |
} |
||
| 11406 |
m0 := mload(0x00) |
||
| 11407 |
m1 := mload(0x20) |
||
| 11408 |
m2 := mload(0x40) |
||
| 11409 |
m3 := mload(0x60) |
||
| 11410 |
m4 := mload(0x80) |
||
| 11411 |
m5 := mload(0xa0) |
||
| 11412 |
m6 := mload(0xc0) |
||
| 11413 |
m7 := mload(0xe0) |
||
| 11414 |
m8 := mload(0x100) |
||
| 11415 |
// Selector of `log(string,address,string,uint256)`. |
||
| 11416 |
mstore(0x00, 0x91d1112e) |
||
| 11417 |
mstore(0x20, 0x80) |
||
| 11418 |
mstore(0x40, p1) |
||
| 11419 |
mstore(0x60, 0xc0) |
||
| 11420 |
mstore(0x80, p3) |
||
| 11421 |
writeString(0xa0, p0) |
||
| 11422 |
writeString(0xe0, p2) |
||
| 11423 |
} |
||
| 11424 |
_sendLogPayload(0x1c, 0x104); |
||
| 11425 |
/// @solidity memory-safe-assembly |
||
| 11426 |
assembly {
|
||
| 11427 |
mstore(0x00, m0) |
||
| 11428 |
mstore(0x20, m1) |
||
| 11429 |
mstore(0x40, m2) |
||
| 11430 |
mstore(0x60, m3) |
||
| 11431 |
mstore(0x80, m4) |
||
| 11432 |
mstore(0xa0, m5) |
||
| 11433 |
mstore(0xc0, m6) |
||
| 11434 |
mstore(0xe0, m7) |
||
| 11435 |
mstore(0x100, m8) |
||
| 11436 |
} |
||
| 11437 |
} |
||
| 11438 | |||
| 11439 |
function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 11440 |
bytes32 m0; |
||
| 11441 |
bytes32 m1; |
||
| 11442 |
bytes32 m2; |
||
| 11443 |
bytes32 m3; |
||
| 11444 |
bytes32 m4; |
||
| 11445 |
bytes32 m5; |
||
| 11446 |
bytes32 m6; |
||
| 11447 |
bytes32 m7; |
||
| 11448 |
bytes32 m8; |
||
| 11449 |
bytes32 m9; |
||
| 11450 |
bytes32 m10; |
||
| 11451 |
/// @solidity memory-safe-assembly |
||
| 11452 |
assembly {
|
||
| 11453 |
function writeString(pos, w) {
|
||
| 11454 |
let length := 0 |
||
| 11455 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11456 |
mstore(pos, length) |
||
| 11457 |
let shift := sub(256, shl(3, length)) |
||
| 11458 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11459 |
} |
||
| 11460 |
m0 := mload(0x00) |
||
| 11461 |
m1 := mload(0x20) |
||
| 11462 |
m2 := mload(0x40) |
||
| 11463 |
m3 := mload(0x60) |
||
| 11464 |
m4 := mload(0x80) |
||
| 11465 |
m5 := mload(0xa0) |
||
| 11466 |
m6 := mload(0xc0) |
||
| 11467 |
m7 := mload(0xe0) |
||
| 11468 |
m8 := mload(0x100) |
||
| 11469 |
m9 := mload(0x120) |
||
| 11470 |
m10 := mload(0x140) |
||
| 11471 |
// Selector of `log(string,address,string,string)`. |
||
| 11472 |
mstore(0x00, 0x245986f2) |
||
| 11473 |
mstore(0x20, 0x80) |
||
| 11474 |
mstore(0x40, p1) |
||
| 11475 |
mstore(0x60, 0xc0) |
||
| 11476 |
mstore(0x80, 0x100) |
||
| 11477 |
writeString(0xa0, p0) |
||
| 11478 |
writeString(0xe0, p2) |
||
| 11479 |
writeString(0x120, p3) |
||
| 11480 |
} |
||
| 11481 |
_sendLogPayload(0x1c, 0x144); |
||
| 11482 |
/// @solidity memory-safe-assembly |
||
| 11483 |
assembly {
|
||
| 11484 |
mstore(0x00, m0) |
||
| 11485 |
mstore(0x20, m1) |
||
| 11486 |
mstore(0x40, m2) |
||
| 11487 |
mstore(0x60, m3) |
||
| 11488 |
mstore(0x80, m4) |
||
| 11489 |
mstore(0xa0, m5) |
||
| 11490 |
mstore(0xc0, m6) |
||
| 11491 |
mstore(0xe0, m7) |
||
| 11492 |
mstore(0x100, m8) |
||
| 11493 |
mstore(0x120, m9) |
||
| 11494 |
mstore(0x140, m10) |
||
| 11495 |
} |
||
| 11496 |
} |
||
| 11497 | |||
| 11498 |
function log(bytes32 p0, bool p1, address p2, address p3) internal pure {
|
||
| 11499 |
bytes32 m0; |
||
| 11500 |
bytes32 m1; |
||
| 11501 |
bytes32 m2; |
||
| 11502 |
bytes32 m3; |
||
| 11503 |
bytes32 m4; |
||
| 11504 |
bytes32 m5; |
||
| 11505 |
bytes32 m6; |
||
| 11506 |
/// @solidity memory-safe-assembly |
||
| 11507 |
assembly {
|
||
| 11508 |
function writeString(pos, w) {
|
||
| 11509 |
let length := 0 |
||
| 11510 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11511 |
mstore(pos, length) |
||
| 11512 |
let shift := sub(256, shl(3, length)) |
||
| 11513 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11514 |
} |
||
| 11515 |
m0 := mload(0x00) |
||
| 11516 |
m1 := mload(0x20) |
||
| 11517 |
m2 := mload(0x40) |
||
| 11518 |
m3 := mload(0x60) |
||
| 11519 |
m4 := mload(0x80) |
||
| 11520 |
m5 := mload(0xa0) |
||
| 11521 |
m6 := mload(0xc0) |
||
| 11522 |
// Selector of `log(string,bool,address,address)`. |
||
| 11523 |
mstore(0x00, 0x33e9dd1d) |
||
| 11524 |
mstore(0x20, 0x80) |
||
| 11525 |
mstore(0x40, p1) |
||
| 11526 |
mstore(0x60, p2) |
||
| 11527 |
mstore(0x80, p3) |
||
| 11528 |
writeString(0xa0, p0) |
||
| 11529 |
} |
||
| 11530 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11531 |
/// @solidity memory-safe-assembly |
||
| 11532 |
assembly {
|
||
| 11533 |
mstore(0x00, m0) |
||
| 11534 |
mstore(0x20, m1) |
||
| 11535 |
mstore(0x40, m2) |
||
| 11536 |
mstore(0x60, m3) |
||
| 11537 |
mstore(0x80, m4) |
||
| 11538 |
mstore(0xa0, m5) |
||
| 11539 |
mstore(0xc0, m6) |
||
| 11540 |
} |
||
| 11541 |
} |
||
| 11542 | |||
| 11543 |
function log(bytes32 p0, bool p1, address p2, bool p3) internal pure {
|
||
| 11544 |
bytes32 m0; |
||
| 11545 |
bytes32 m1; |
||
| 11546 |
bytes32 m2; |
||
| 11547 |
bytes32 m3; |
||
| 11548 |
bytes32 m4; |
||
| 11549 |
bytes32 m5; |
||
| 11550 |
bytes32 m6; |
||
| 11551 |
/// @solidity memory-safe-assembly |
||
| 11552 |
assembly {
|
||
| 11553 |
function writeString(pos, w) {
|
||
| 11554 |
let length := 0 |
||
| 11555 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11556 |
mstore(pos, length) |
||
| 11557 |
let shift := sub(256, shl(3, length)) |
||
| 11558 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11559 |
} |
||
| 11560 |
m0 := mload(0x00) |
||
| 11561 |
m1 := mload(0x20) |
||
| 11562 |
m2 := mload(0x40) |
||
| 11563 |
m3 := mload(0x60) |
||
| 11564 |
m4 := mload(0x80) |
||
| 11565 |
m5 := mload(0xa0) |
||
| 11566 |
m6 := mload(0xc0) |
||
| 11567 |
// Selector of `log(string,bool,address,bool)`. |
||
| 11568 |
mstore(0x00, 0x958c28c6) |
||
| 11569 |
mstore(0x20, 0x80) |
||
| 11570 |
mstore(0x40, p1) |
||
| 11571 |
mstore(0x60, p2) |
||
| 11572 |
mstore(0x80, p3) |
||
| 11573 |
writeString(0xa0, p0) |
||
| 11574 |
} |
||
| 11575 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11576 |
/// @solidity memory-safe-assembly |
||
| 11577 |
assembly {
|
||
| 11578 |
mstore(0x00, m0) |
||
| 11579 |
mstore(0x20, m1) |
||
| 11580 |
mstore(0x40, m2) |
||
| 11581 |
mstore(0x60, m3) |
||
| 11582 |
mstore(0x80, m4) |
||
| 11583 |
mstore(0xa0, m5) |
||
| 11584 |
mstore(0xc0, m6) |
||
| 11585 |
} |
||
| 11586 |
} |
||
| 11587 | |||
| 11588 |
function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure {
|
||
| 11589 |
bytes32 m0; |
||
| 11590 |
bytes32 m1; |
||
| 11591 |
bytes32 m2; |
||
| 11592 |
bytes32 m3; |
||
| 11593 |
bytes32 m4; |
||
| 11594 |
bytes32 m5; |
||
| 11595 |
bytes32 m6; |
||
| 11596 |
/// @solidity memory-safe-assembly |
||
| 11597 |
assembly {
|
||
| 11598 |
function writeString(pos, w) {
|
||
| 11599 |
let length := 0 |
||
| 11600 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11601 |
mstore(pos, length) |
||
| 11602 |
let shift := sub(256, shl(3, length)) |
||
| 11603 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11604 |
} |
||
| 11605 |
m0 := mload(0x00) |
||
| 11606 |
m1 := mload(0x20) |
||
| 11607 |
m2 := mload(0x40) |
||
| 11608 |
m3 := mload(0x60) |
||
| 11609 |
m4 := mload(0x80) |
||
| 11610 |
m5 := mload(0xa0) |
||
| 11611 |
m6 := mload(0xc0) |
||
| 11612 |
// Selector of `log(string,bool,address,uint256)`. |
||
| 11613 |
mstore(0x00, 0x5d08bb05) |
||
| 11614 |
mstore(0x20, 0x80) |
||
| 11615 |
mstore(0x40, p1) |
||
| 11616 |
mstore(0x60, p2) |
||
| 11617 |
mstore(0x80, p3) |
||
| 11618 |
writeString(0xa0, p0) |
||
| 11619 |
} |
||
| 11620 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11621 |
/// @solidity memory-safe-assembly |
||
| 11622 |
assembly {
|
||
| 11623 |
mstore(0x00, m0) |
||
| 11624 |
mstore(0x20, m1) |
||
| 11625 |
mstore(0x40, m2) |
||
| 11626 |
mstore(0x60, m3) |
||
| 11627 |
mstore(0x80, m4) |
||
| 11628 |
mstore(0xa0, m5) |
||
| 11629 |
mstore(0xc0, m6) |
||
| 11630 |
} |
||
| 11631 |
} |
||
| 11632 | |||
| 11633 |
function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure {
|
||
| 11634 |
bytes32 m0; |
||
| 11635 |
bytes32 m1; |
||
| 11636 |
bytes32 m2; |
||
| 11637 |
bytes32 m3; |
||
| 11638 |
bytes32 m4; |
||
| 11639 |
bytes32 m5; |
||
| 11640 |
bytes32 m6; |
||
| 11641 |
bytes32 m7; |
||
| 11642 |
bytes32 m8; |
||
| 11643 |
/// @solidity memory-safe-assembly |
||
| 11644 |
assembly {
|
||
| 11645 |
function writeString(pos, w) {
|
||
| 11646 |
let length := 0 |
||
| 11647 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11648 |
mstore(pos, length) |
||
| 11649 |
let shift := sub(256, shl(3, length)) |
||
| 11650 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11651 |
} |
||
| 11652 |
m0 := mload(0x00) |
||
| 11653 |
m1 := mload(0x20) |
||
| 11654 |
m2 := mload(0x40) |
||
| 11655 |
m3 := mload(0x60) |
||
| 11656 |
m4 := mload(0x80) |
||
| 11657 |
m5 := mload(0xa0) |
||
| 11658 |
m6 := mload(0xc0) |
||
| 11659 |
m7 := mload(0xe0) |
||
| 11660 |
m8 := mload(0x100) |
||
| 11661 |
// Selector of `log(string,bool,address,string)`. |
||
| 11662 |
mstore(0x00, 0x2d8e33a4) |
||
| 11663 |
mstore(0x20, 0x80) |
||
| 11664 |
mstore(0x40, p1) |
||
| 11665 |
mstore(0x60, p2) |
||
| 11666 |
mstore(0x80, 0xc0) |
||
| 11667 |
writeString(0xa0, p0) |
||
| 11668 |
writeString(0xe0, p3) |
||
| 11669 |
} |
||
| 11670 |
_sendLogPayload(0x1c, 0x104); |
||
| 11671 |
/// @solidity memory-safe-assembly |
||
| 11672 |
assembly {
|
||
| 11673 |
mstore(0x00, m0) |
||
| 11674 |
mstore(0x20, m1) |
||
| 11675 |
mstore(0x40, m2) |
||
| 11676 |
mstore(0x60, m3) |
||
| 11677 |
mstore(0x80, m4) |
||
| 11678 |
mstore(0xa0, m5) |
||
| 11679 |
mstore(0xc0, m6) |
||
| 11680 |
mstore(0xe0, m7) |
||
| 11681 |
mstore(0x100, m8) |
||
| 11682 |
} |
||
| 11683 |
} |
||
| 11684 | |||
| 11685 |
function log(bytes32 p0, bool p1, bool p2, address p3) internal pure {
|
||
| 11686 |
bytes32 m0; |
||
| 11687 |
bytes32 m1; |
||
| 11688 |
bytes32 m2; |
||
| 11689 |
bytes32 m3; |
||
| 11690 |
bytes32 m4; |
||
| 11691 |
bytes32 m5; |
||
| 11692 |
bytes32 m6; |
||
| 11693 |
/// @solidity memory-safe-assembly |
||
| 11694 |
assembly {
|
||
| 11695 |
function writeString(pos, w) {
|
||
| 11696 |
let length := 0 |
||
| 11697 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11698 |
mstore(pos, length) |
||
| 11699 |
let shift := sub(256, shl(3, length)) |
||
| 11700 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11701 |
} |
||
| 11702 |
m0 := mload(0x00) |
||
| 11703 |
m1 := mload(0x20) |
||
| 11704 |
m2 := mload(0x40) |
||
| 11705 |
m3 := mload(0x60) |
||
| 11706 |
m4 := mload(0x80) |
||
| 11707 |
m5 := mload(0xa0) |
||
| 11708 |
m6 := mload(0xc0) |
||
| 11709 |
// Selector of `log(string,bool,bool,address)`. |
||
| 11710 |
mstore(0x00, 0x7190a529) |
||
| 11711 |
mstore(0x20, 0x80) |
||
| 11712 |
mstore(0x40, p1) |
||
| 11713 |
mstore(0x60, p2) |
||
| 11714 |
mstore(0x80, p3) |
||
| 11715 |
writeString(0xa0, p0) |
||
| 11716 |
} |
||
| 11717 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11718 |
/// @solidity memory-safe-assembly |
||
| 11719 |
assembly {
|
||
| 11720 |
mstore(0x00, m0) |
||
| 11721 |
mstore(0x20, m1) |
||
| 11722 |
mstore(0x40, m2) |
||
| 11723 |
mstore(0x60, m3) |
||
| 11724 |
mstore(0x80, m4) |
||
| 11725 |
mstore(0xa0, m5) |
||
| 11726 |
mstore(0xc0, m6) |
||
| 11727 |
} |
||
| 11728 |
} |
||
| 11729 | |||
| 11730 |
function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure {
|
||
| 11731 |
bytes32 m0; |
||
| 11732 |
bytes32 m1; |
||
| 11733 |
bytes32 m2; |
||
| 11734 |
bytes32 m3; |
||
| 11735 |
bytes32 m4; |
||
| 11736 |
bytes32 m5; |
||
| 11737 |
bytes32 m6; |
||
| 11738 |
/// @solidity memory-safe-assembly |
||
| 11739 |
assembly {
|
||
| 11740 |
function writeString(pos, w) {
|
||
| 11741 |
let length := 0 |
||
| 11742 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11743 |
mstore(pos, length) |
||
| 11744 |
let shift := sub(256, shl(3, length)) |
||
| 11745 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11746 |
} |
||
| 11747 |
m0 := mload(0x00) |
||
| 11748 |
m1 := mload(0x20) |
||
| 11749 |
m2 := mload(0x40) |
||
| 11750 |
m3 := mload(0x60) |
||
| 11751 |
m4 := mload(0x80) |
||
| 11752 |
m5 := mload(0xa0) |
||
| 11753 |
m6 := mload(0xc0) |
||
| 11754 |
// Selector of `log(string,bool,bool,bool)`. |
||
| 11755 |
mstore(0x00, 0x895af8c5) |
||
| 11756 |
mstore(0x20, 0x80) |
||
| 11757 |
mstore(0x40, p1) |
||
| 11758 |
mstore(0x60, p2) |
||
| 11759 |
mstore(0x80, p3) |
||
| 11760 |
writeString(0xa0, p0) |
||
| 11761 |
} |
||
| 11762 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11763 |
/// @solidity memory-safe-assembly |
||
| 11764 |
assembly {
|
||
| 11765 |
mstore(0x00, m0) |
||
| 11766 |
mstore(0x20, m1) |
||
| 11767 |
mstore(0x40, m2) |
||
| 11768 |
mstore(0x60, m3) |
||
| 11769 |
mstore(0x80, m4) |
||
| 11770 |
mstore(0xa0, m5) |
||
| 11771 |
mstore(0xc0, m6) |
||
| 11772 |
} |
||
| 11773 |
} |
||
| 11774 | |||
| 11775 |
function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure {
|
||
| 11776 |
bytes32 m0; |
||
| 11777 |
bytes32 m1; |
||
| 11778 |
bytes32 m2; |
||
| 11779 |
bytes32 m3; |
||
| 11780 |
bytes32 m4; |
||
| 11781 |
bytes32 m5; |
||
| 11782 |
bytes32 m6; |
||
| 11783 |
/// @solidity memory-safe-assembly |
||
| 11784 |
assembly {
|
||
| 11785 |
function writeString(pos, w) {
|
||
| 11786 |
let length := 0 |
||
| 11787 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11788 |
mstore(pos, length) |
||
| 11789 |
let shift := sub(256, shl(3, length)) |
||
| 11790 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11791 |
} |
||
| 11792 |
m0 := mload(0x00) |
||
| 11793 |
m1 := mload(0x20) |
||
| 11794 |
m2 := mload(0x40) |
||
| 11795 |
m3 := mload(0x60) |
||
| 11796 |
m4 := mload(0x80) |
||
| 11797 |
m5 := mload(0xa0) |
||
| 11798 |
m6 := mload(0xc0) |
||
| 11799 |
// Selector of `log(string,bool,bool,uint256)`. |
||
| 11800 |
mstore(0x00, 0x8e3f78a9) |
||
| 11801 |
mstore(0x20, 0x80) |
||
| 11802 |
mstore(0x40, p1) |
||
| 11803 |
mstore(0x60, p2) |
||
| 11804 |
mstore(0x80, p3) |
||
| 11805 |
writeString(0xa0, p0) |
||
| 11806 |
} |
||
| 11807 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11808 |
/// @solidity memory-safe-assembly |
||
| 11809 |
assembly {
|
||
| 11810 |
mstore(0x00, m0) |
||
| 11811 |
mstore(0x20, m1) |
||
| 11812 |
mstore(0x40, m2) |
||
| 11813 |
mstore(0x60, m3) |
||
| 11814 |
mstore(0x80, m4) |
||
| 11815 |
mstore(0xa0, m5) |
||
| 11816 |
mstore(0xc0, m6) |
||
| 11817 |
} |
||
| 11818 |
} |
||
| 11819 | |||
| 11820 |
function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure {
|
||
| 11821 |
bytes32 m0; |
||
| 11822 |
bytes32 m1; |
||
| 11823 |
bytes32 m2; |
||
| 11824 |
bytes32 m3; |
||
| 11825 |
bytes32 m4; |
||
| 11826 |
bytes32 m5; |
||
| 11827 |
bytes32 m6; |
||
| 11828 |
bytes32 m7; |
||
| 11829 |
bytes32 m8; |
||
| 11830 |
/// @solidity memory-safe-assembly |
||
| 11831 |
assembly {
|
||
| 11832 |
function writeString(pos, w) {
|
||
| 11833 |
let length := 0 |
||
| 11834 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11835 |
mstore(pos, length) |
||
| 11836 |
let shift := sub(256, shl(3, length)) |
||
| 11837 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11838 |
} |
||
| 11839 |
m0 := mload(0x00) |
||
| 11840 |
m1 := mload(0x20) |
||
| 11841 |
m2 := mload(0x40) |
||
| 11842 |
m3 := mload(0x60) |
||
| 11843 |
m4 := mload(0x80) |
||
| 11844 |
m5 := mload(0xa0) |
||
| 11845 |
m6 := mload(0xc0) |
||
| 11846 |
m7 := mload(0xe0) |
||
| 11847 |
m8 := mload(0x100) |
||
| 11848 |
// Selector of `log(string,bool,bool,string)`. |
||
| 11849 |
mstore(0x00, 0x9d22d5dd) |
||
| 11850 |
mstore(0x20, 0x80) |
||
| 11851 |
mstore(0x40, p1) |
||
| 11852 |
mstore(0x60, p2) |
||
| 11853 |
mstore(0x80, 0xc0) |
||
| 11854 |
writeString(0xa0, p0) |
||
| 11855 |
writeString(0xe0, p3) |
||
| 11856 |
} |
||
| 11857 |
_sendLogPayload(0x1c, 0x104); |
||
| 11858 |
/// @solidity memory-safe-assembly |
||
| 11859 |
assembly {
|
||
| 11860 |
mstore(0x00, m0) |
||
| 11861 |
mstore(0x20, m1) |
||
| 11862 |
mstore(0x40, m2) |
||
| 11863 |
mstore(0x60, m3) |
||
| 11864 |
mstore(0x80, m4) |
||
| 11865 |
mstore(0xa0, m5) |
||
| 11866 |
mstore(0xc0, m6) |
||
| 11867 |
mstore(0xe0, m7) |
||
| 11868 |
mstore(0x100, m8) |
||
| 11869 |
} |
||
| 11870 |
} |
||
| 11871 | |||
| 11872 |
function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure {
|
||
| 11873 |
bytes32 m0; |
||
| 11874 |
bytes32 m1; |
||
| 11875 |
bytes32 m2; |
||
| 11876 |
bytes32 m3; |
||
| 11877 |
bytes32 m4; |
||
| 11878 |
bytes32 m5; |
||
| 11879 |
bytes32 m6; |
||
| 11880 |
/// @solidity memory-safe-assembly |
||
| 11881 |
assembly {
|
||
| 11882 |
function writeString(pos, w) {
|
||
| 11883 |
let length := 0 |
||
| 11884 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11885 |
mstore(pos, length) |
||
| 11886 |
let shift := sub(256, shl(3, length)) |
||
| 11887 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11888 |
} |
||
| 11889 |
m0 := mload(0x00) |
||
| 11890 |
m1 := mload(0x20) |
||
| 11891 |
m2 := mload(0x40) |
||
| 11892 |
m3 := mload(0x60) |
||
| 11893 |
m4 := mload(0x80) |
||
| 11894 |
m5 := mload(0xa0) |
||
| 11895 |
m6 := mload(0xc0) |
||
| 11896 |
// Selector of `log(string,bool,uint256,address)`. |
||
| 11897 |
mstore(0x00, 0x935e09bf) |
||
| 11898 |
mstore(0x20, 0x80) |
||
| 11899 |
mstore(0x40, p1) |
||
| 11900 |
mstore(0x60, p2) |
||
| 11901 |
mstore(0x80, p3) |
||
| 11902 |
writeString(0xa0, p0) |
||
| 11903 |
} |
||
| 11904 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11905 |
/// @solidity memory-safe-assembly |
||
| 11906 |
assembly {
|
||
| 11907 |
mstore(0x00, m0) |
||
| 11908 |
mstore(0x20, m1) |
||
| 11909 |
mstore(0x40, m2) |
||
| 11910 |
mstore(0x60, m3) |
||
| 11911 |
mstore(0x80, m4) |
||
| 11912 |
mstore(0xa0, m5) |
||
| 11913 |
mstore(0xc0, m6) |
||
| 11914 |
} |
||
| 11915 |
} |
||
| 11916 | |||
| 11917 |
function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure {
|
||
| 11918 |
bytes32 m0; |
||
| 11919 |
bytes32 m1; |
||
| 11920 |
bytes32 m2; |
||
| 11921 |
bytes32 m3; |
||
| 11922 |
bytes32 m4; |
||
| 11923 |
bytes32 m5; |
||
| 11924 |
bytes32 m6; |
||
| 11925 |
/// @solidity memory-safe-assembly |
||
| 11926 |
assembly {
|
||
| 11927 |
function writeString(pos, w) {
|
||
| 11928 |
let length := 0 |
||
| 11929 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11930 |
mstore(pos, length) |
||
| 11931 |
let shift := sub(256, shl(3, length)) |
||
| 11932 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11933 |
} |
||
| 11934 |
m0 := mload(0x00) |
||
| 11935 |
m1 := mload(0x20) |
||
| 11936 |
m2 := mload(0x40) |
||
| 11937 |
m3 := mload(0x60) |
||
| 11938 |
m4 := mload(0x80) |
||
| 11939 |
m5 := mload(0xa0) |
||
| 11940 |
m6 := mload(0xc0) |
||
| 11941 |
// Selector of `log(string,bool,uint256,bool)`. |
||
| 11942 |
mstore(0x00, 0x8af7cf8a) |
||
| 11943 |
mstore(0x20, 0x80) |
||
| 11944 |
mstore(0x40, p1) |
||
| 11945 |
mstore(0x60, p2) |
||
| 11946 |
mstore(0x80, p3) |
||
| 11947 |
writeString(0xa0, p0) |
||
| 11948 |
} |
||
| 11949 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11950 |
/// @solidity memory-safe-assembly |
||
| 11951 |
assembly {
|
||
| 11952 |
mstore(0x00, m0) |
||
| 11953 |
mstore(0x20, m1) |
||
| 11954 |
mstore(0x40, m2) |
||
| 11955 |
mstore(0x60, m3) |
||
| 11956 |
mstore(0x80, m4) |
||
| 11957 |
mstore(0xa0, m5) |
||
| 11958 |
mstore(0xc0, m6) |
||
| 11959 |
} |
||
| 11960 |
} |
||
| 11961 | |||
| 11962 |
function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure {
|
||
| 11963 |
bytes32 m0; |
||
| 11964 |
bytes32 m1; |
||
| 11965 |
bytes32 m2; |
||
| 11966 |
bytes32 m3; |
||
| 11967 |
bytes32 m4; |
||
| 11968 |
bytes32 m5; |
||
| 11969 |
bytes32 m6; |
||
| 11970 |
/// @solidity memory-safe-assembly |
||
| 11971 |
assembly {
|
||
| 11972 |
function writeString(pos, w) {
|
||
| 11973 |
let length := 0 |
||
| 11974 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 11975 |
mstore(pos, length) |
||
| 11976 |
let shift := sub(256, shl(3, length)) |
||
| 11977 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 11978 |
} |
||
| 11979 |
m0 := mload(0x00) |
||
| 11980 |
m1 := mload(0x20) |
||
| 11981 |
m2 := mload(0x40) |
||
| 11982 |
m3 := mload(0x60) |
||
| 11983 |
m4 := mload(0x80) |
||
| 11984 |
m5 := mload(0xa0) |
||
| 11985 |
m6 := mload(0xc0) |
||
| 11986 |
// Selector of `log(string,bool,uint256,uint256)`. |
||
| 11987 |
mstore(0x00, 0x64b5bb67) |
||
| 11988 |
mstore(0x20, 0x80) |
||
| 11989 |
mstore(0x40, p1) |
||
| 11990 |
mstore(0x60, p2) |
||
| 11991 |
mstore(0x80, p3) |
||
| 11992 |
writeString(0xa0, p0) |
||
| 11993 |
} |
||
| 11994 |
_sendLogPayload(0x1c, 0xc4); |
||
| 11995 |
/// @solidity memory-safe-assembly |
||
| 11996 |
assembly {
|
||
| 11997 |
mstore(0x00, m0) |
||
| 11998 |
mstore(0x20, m1) |
||
| 11999 |
mstore(0x40, m2) |
||
| 12000 |
mstore(0x60, m3) |
||
| 12001 |
mstore(0x80, m4) |
||
| 12002 |
mstore(0xa0, m5) |
||
| 12003 |
mstore(0xc0, m6) |
||
| 12004 |
} |
||
| 12005 |
} |
||
| 12006 | |||
| 12007 |
function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 12008 |
bytes32 m0; |
||
| 12009 |
bytes32 m1; |
||
| 12010 |
bytes32 m2; |
||
| 12011 |
bytes32 m3; |
||
| 12012 |
bytes32 m4; |
||
| 12013 |
bytes32 m5; |
||
| 12014 |
bytes32 m6; |
||
| 12015 |
bytes32 m7; |
||
| 12016 |
bytes32 m8; |
||
| 12017 |
/// @solidity memory-safe-assembly |
||
| 12018 |
assembly {
|
||
| 12019 |
function writeString(pos, w) {
|
||
| 12020 |
let length := 0 |
||
| 12021 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12022 |
mstore(pos, length) |
||
| 12023 |
let shift := sub(256, shl(3, length)) |
||
| 12024 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12025 |
} |
||
| 12026 |
m0 := mload(0x00) |
||
| 12027 |
m1 := mload(0x20) |
||
| 12028 |
m2 := mload(0x40) |
||
| 12029 |
m3 := mload(0x60) |
||
| 12030 |
m4 := mload(0x80) |
||
| 12031 |
m5 := mload(0xa0) |
||
| 12032 |
m6 := mload(0xc0) |
||
| 12033 |
m7 := mload(0xe0) |
||
| 12034 |
m8 := mload(0x100) |
||
| 12035 |
// Selector of `log(string,bool,uint256,string)`. |
||
| 12036 |
mstore(0x00, 0x742d6ee7) |
||
| 12037 |
mstore(0x20, 0x80) |
||
| 12038 |
mstore(0x40, p1) |
||
| 12039 |
mstore(0x60, p2) |
||
| 12040 |
mstore(0x80, 0xc0) |
||
| 12041 |
writeString(0xa0, p0) |
||
| 12042 |
writeString(0xe0, p3) |
||
| 12043 |
} |
||
| 12044 |
_sendLogPayload(0x1c, 0x104); |
||
| 12045 |
/// @solidity memory-safe-assembly |
||
| 12046 |
assembly {
|
||
| 12047 |
mstore(0x00, m0) |
||
| 12048 |
mstore(0x20, m1) |
||
| 12049 |
mstore(0x40, m2) |
||
| 12050 |
mstore(0x60, m3) |
||
| 12051 |
mstore(0x80, m4) |
||
| 12052 |
mstore(0xa0, m5) |
||
| 12053 |
mstore(0xc0, m6) |
||
| 12054 |
mstore(0xe0, m7) |
||
| 12055 |
mstore(0x100, m8) |
||
| 12056 |
} |
||
| 12057 |
} |
||
| 12058 | |||
| 12059 |
function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure {
|
||
| 12060 |
bytes32 m0; |
||
| 12061 |
bytes32 m1; |
||
| 12062 |
bytes32 m2; |
||
| 12063 |
bytes32 m3; |
||
| 12064 |
bytes32 m4; |
||
| 12065 |
bytes32 m5; |
||
| 12066 |
bytes32 m6; |
||
| 12067 |
bytes32 m7; |
||
| 12068 |
bytes32 m8; |
||
| 12069 |
/// @solidity memory-safe-assembly |
||
| 12070 |
assembly {
|
||
| 12071 |
function writeString(pos, w) {
|
||
| 12072 |
let length := 0 |
||
| 12073 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12074 |
mstore(pos, length) |
||
| 12075 |
let shift := sub(256, shl(3, length)) |
||
| 12076 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12077 |
} |
||
| 12078 |
m0 := mload(0x00) |
||
| 12079 |
m1 := mload(0x20) |
||
| 12080 |
m2 := mload(0x40) |
||
| 12081 |
m3 := mload(0x60) |
||
| 12082 |
m4 := mload(0x80) |
||
| 12083 |
m5 := mload(0xa0) |
||
| 12084 |
m6 := mload(0xc0) |
||
| 12085 |
m7 := mload(0xe0) |
||
| 12086 |
m8 := mload(0x100) |
||
| 12087 |
// Selector of `log(string,bool,string,address)`. |
||
| 12088 |
mstore(0x00, 0xe0625b29) |
||
| 12089 |
mstore(0x20, 0x80) |
||
| 12090 |
mstore(0x40, p1) |
||
| 12091 |
mstore(0x60, 0xc0) |
||
| 12092 |
mstore(0x80, p3) |
||
| 12093 |
writeString(0xa0, p0) |
||
| 12094 |
writeString(0xe0, p2) |
||
| 12095 |
} |
||
| 12096 |
_sendLogPayload(0x1c, 0x104); |
||
| 12097 |
/// @solidity memory-safe-assembly |
||
| 12098 |
assembly {
|
||
| 12099 |
mstore(0x00, m0) |
||
| 12100 |
mstore(0x20, m1) |
||
| 12101 |
mstore(0x40, m2) |
||
| 12102 |
mstore(0x60, m3) |
||
| 12103 |
mstore(0x80, m4) |
||
| 12104 |
mstore(0xa0, m5) |
||
| 12105 |
mstore(0xc0, m6) |
||
| 12106 |
mstore(0xe0, m7) |
||
| 12107 |
mstore(0x100, m8) |
||
| 12108 |
} |
||
| 12109 |
} |
||
| 12110 | |||
| 12111 |
function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure {
|
||
| 12112 |
bytes32 m0; |
||
| 12113 |
bytes32 m1; |
||
| 12114 |
bytes32 m2; |
||
| 12115 |
bytes32 m3; |
||
| 12116 |
bytes32 m4; |
||
| 12117 |
bytes32 m5; |
||
| 12118 |
bytes32 m6; |
||
| 12119 |
bytes32 m7; |
||
| 12120 |
bytes32 m8; |
||
| 12121 |
/// @solidity memory-safe-assembly |
||
| 12122 |
assembly {
|
||
| 12123 |
function writeString(pos, w) {
|
||
| 12124 |
let length := 0 |
||
| 12125 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12126 |
mstore(pos, length) |
||
| 12127 |
let shift := sub(256, shl(3, length)) |
||
| 12128 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12129 |
} |
||
| 12130 |
m0 := mload(0x00) |
||
| 12131 |
m1 := mload(0x20) |
||
| 12132 |
m2 := mload(0x40) |
||
| 12133 |
m3 := mload(0x60) |
||
| 12134 |
m4 := mload(0x80) |
||
| 12135 |
m5 := mload(0xa0) |
||
| 12136 |
m6 := mload(0xc0) |
||
| 12137 |
m7 := mload(0xe0) |
||
| 12138 |
m8 := mload(0x100) |
||
| 12139 |
// Selector of `log(string,bool,string,bool)`. |
||
| 12140 |
mstore(0x00, 0x3f8a701d) |
||
| 12141 |
mstore(0x20, 0x80) |
||
| 12142 |
mstore(0x40, p1) |
||
| 12143 |
mstore(0x60, 0xc0) |
||
| 12144 |
mstore(0x80, p3) |
||
| 12145 |
writeString(0xa0, p0) |
||
| 12146 |
writeString(0xe0, p2) |
||
| 12147 |
} |
||
| 12148 |
_sendLogPayload(0x1c, 0x104); |
||
| 12149 |
/// @solidity memory-safe-assembly |
||
| 12150 |
assembly {
|
||
| 12151 |
mstore(0x00, m0) |
||
| 12152 |
mstore(0x20, m1) |
||
| 12153 |
mstore(0x40, m2) |
||
| 12154 |
mstore(0x60, m3) |
||
| 12155 |
mstore(0x80, m4) |
||
| 12156 |
mstore(0xa0, m5) |
||
| 12157 |
mstore(0xc0, m6) |
||
| 12158 |
mstore(0xe0, m7) |
||
| 12159 |
mstore(0x100, m8) |
||
| 12160 |
} |
||
| 12161 |
} |
||
| 12162 | |||
| 12163 |
function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 12164 |
bytes32 m0; |
||
| 12165 |
bytes32 m1; |
||
| 12166 |
bytes32 m2; |
||
| 12167 |
bytes32 m3; |
||
| 12168 |
bytes32 m4; |
||
| 12169 |
bytes32 m5; |
||
| 12170 |
bytes32 m6; |
||
| 12171 |
bytes32 m7; |
||
| 12172 |
bytes32 m8; |
||
| 12173 |
/// @solidity memory-safe-assembly |
||
| 12174 |
assembly {
|
||
| 12175 |
function writeString(pos, w) {
|
||
| 12176 |
let length := 0 |
||
| 12177 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12178 |
mstore(pos, length) |
||
| 12179 |
let shift := sub(256, shl(3, length)) |
||
| 12180 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12181 |
} |
||
| 12182 |
m0 := mload(0x00) |
||
| 12183 |
m1 := mload(0x20) |
||
| 12184 |
m2 := mload(0x40) |
||
| 12185 |
m3 := mload(0x60) |
||
| 12186 |
m4 := mload(0x80) |
||
| 12187 |
m5 := mload(0xa0) |
||
| 12188 |
m6 := mload(0xc0) |
||
| 12189 |
m7 := mload(0xe0) |
||
| 12190 |
m8 := mload(0x100) |
||
| 12191 |
// Selector of `log(string,bool,string,uint256)`. |
||
| 12192 |
mstore(0x00, 0x24f91465) |
||
| 12193 |
mstore(0x20, 0x80) |
||
| 12194 |
mstore(0x40, p1) |
||
| 12195 |
mstore(0x60, 0xc0) |
||
| 12196 |
mstore(0x80, p3) |
||
| 12197 |
writeString(0xa0, p0) |
||
| 12198 |
writeString(0xe0, p2) |
||
| 12199 |
} |
||
| 12200 |
_sendLogPayload(0x1c, 0x104); |
||
| 12201 |
/// @solidity memory-safe-assembly |
||
| 12202 |
assembly {
|
||
| 12203 |
mstore(0x00, m0) |
||
| 12204 |
mstore(0x20, m1) |
||
| 12205 |
mstore(0x40, m2) |
||
| 12206 |
mstore(0x60, m3) |
||
| 12207 |
mstore(0x80, m4) |
||
| 12208 |
mstore(0xa0, m5) |
||
| 12209 |
mstore(0xc0, m6) |
||
| 12210 |
mstore(0xe0, m7) |
||
| 12211 |
mstore(0x100, m8) |
||
| 12212 |
} |
||
| 12213 |
} |
||
| 12214 | |||
| 12215 |
function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 12216 |
bytes32 m0; |
||
| 12217 |
bytes32 m1; |
||
| 12218 |
bytes32 m2; |
||
| 12219 |
bytes32 m3; |
||
| 12220 |
bytes32 m4; |
||
| 12221 |
bytes32 m5; |
||
| 12222 |
bytes32 m6; |
||
| 12223 |
bytes32 m7; |
||
| 12224 |
bytes32 m8; |
||
| 12225 |
bytes32 m9; |
||
| 12226 |
bytes32 m10; |
||
| 12227 |
/// @solidity memory-safe-assembly |
||
| 12228 |
assembly {
|
||
| 12229 |
function writeString(pos, w) {
|
||
| 12230 |
let length := 0 |
||
| 12231 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12232 |
mstore(pos, length) |
||
| 12233 |
let shift := sub(256, shl(3, length)) |
||
| 12234 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12235 |
} |
||
| 12236 |
m0 := mload(0x00) |
||
| 12237 |
m1 := mload(0x20) |
||
| 12238 |
m2 := mload(0x40) |
||
| 12239 |
m3 := mload(0x60) |
||
| 12240 |
m4 := mload(0x80) |
||
| 12241 |
m5 := mload(0xa0) |
||
| 12242 |
m6 := mload(0xc0) |
||
| 12243 |
m7 := mload(0xe0) |
||
| 12244 |
m8 := mload(0x100) |
||
| 12245 |
m9 := mload(0x120) |
||
| 12246 |
m10 := mload(0x140) |
||
| 12247 |
// Selector of `log(string,bool,string,string)`. |
||
| 12248 |
mstore(0x00, 0xa826caeb) |
||
| 12249 |
mstore(0x20, 0x80) |
||
| 12250 |
mstore(0x40, p1) |
||
| 12251 |
mstore(0x60, 0xc0) |
||
| 12252 |
mstore(0x80, 0x100) |
||
| 12253 |
writeString(0xa0, p0) |
||
| 12254 |
writeString(0xe0, p2) |
||
| 12255 |
writeString(0x120, p3) |
||
| 12256 |
} |
||
| 12257 |
_sendLogPayload(0x1c, 0x144); |
||
| 12258 |
/// @solidity memory-safe-assembly |
||
| 12259 |
assembly {
|
||
| 12260 |
mstore(0x00, m0) |
||
| 12261 |
mstore(0x20, m1) |
||
| 12262 |
mstore(0x40, m2) |
||
| 12263 |
mstore(0x60, m3) |
||
| 12264 |
mstore(0x80, m4) |
||
| 12265 |
mstore(0xa0, m5) |
||
| 12266 |
mstore(0xc0, m6) |
||
| 12267 |
mstore(0xe0, m7) |
||
| 12268 |
mstore(0x100, m8) |
||
| 12269 |
mstore(0x120, m9) |
||
| 12270 |
mstore(0x140, m10) |
||
| 12271 |
} |
||
| 12272 |
} |
||
| 12273 | |||
| 12274 |
function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure {
|
||
| 12275 |
bytes32 m0; |
||
| 12276 |
bytes32 m1; |
||
| 12277 |
bytes32 m2; |
||
| 12278 |
bytes32 m3; |
||
| 12279 |
bytes32 m4; |
||
| 12280 |
bytes32 m5; |
||
| 12281 |
bytes32 m6; |
||
| 12282 |
/// @solidity memory-safe-assembly |
||
| 12283 |
assembly {
|
||
| 12284 |
function writeString(pos, w) {
|
||
| 12285 |
let length := 0 |
||
| 12286 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12287 |
mstore(pos, length) |
||
| 12288 |
let shift := sub(256, shl(3, length)) |
||
| 12289 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12290 |
} |
||
| 12291 |
m0 := mload(0x00) |
||
| 12292 |
m1 := mload(0x20) |
||
| 12293 |
m2 := mload(0x40) |
||
| 12294 |
m3 := mload(0x60) |
||
| 12295 |
m4 := mload(0x80) |
||
| 12296 |
m5 := mload(0xa0) |
||
| 12297 |
m6 := mload(0xc0) |
||
| 12298 |
// Selector of `log(string,uint256,address,address)`. |
||
| 12299 |
mstore(0x00, 0x5ea2b7ae) |
||
| 12300 |
mstore(0x20, 0x80) |
||
| 12301 |
mstore(0x40, p1) |
||
| 12302 |
mstore(0x60, p2) |
||
| 12303 |
mstore(0x80, p3) |
||
| 12304 |
writeString(0xa0, p0) |
||
| 12305 |
} |
||
| 12306 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12307 |
/// @solidity memory-safe-assembly |
||
| 12308 |
assembly {
|
||
| 12309 |
mstore(0x00, m0) |
||
| 12310 |
mstore(0x20, m1) |
||
| 12311 |
mstore(0x40, m2) |
||
| 12312 |
mstore(0x60, m3) |
||
| 12313 |
mstore(0x80, m4) |
||
| 12314 |
mstore(0xa0, m5) |
||
| 12315 |
mstore(0xc0, m6) |
||
| 12316 |
} |
||
| 12317 |
} |
||
| 12318 | |||
| 12319 |
function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure {
|
||
| 12320 |
bytes32 m0; |
||
| 12321 |
bytes32 m1; |
||
| 12322 |
bytes32 m2; |
||
| 12323 |
bytes32 m3; |
||
| 12324 |
bytes32 m4; |
||
| 12325 |
bytes32 m5; |
||
| 12326 |
bytes32 m6; |
||
| 12327 |
/// @solidity memory-safe-assembly |
||
| 12328 |
assembly {
|
||
| 12329 |
function writeString(pos, w) {
|
||
| 12330 |
let length := 0 |
||
| 12331 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12332 |
mstore(pos, length) |
||
| 12333 |
let shift := sub(256, shl(3, length)) |
||
| 12334 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12335 |
} |
||
| 12336 |
m0 := mload(0x00) |
||
| 12337 |
m1 := mload(0x20) |
||
| 12338 |
m2 := mload(0x40) |
||
| 12339 |
m3 := mload(0x60) |
||
| 12340 |
m4 := mload(0x80) |
||
| 12341 |
m5 := mload(0xa0) |
||
| 12342 |
m6 := mload(0xc0) |
||
| 12343 |
// Selector of `log(string,uint256,address,bool)`. |
||
| 12344 |
mstore(0x00, 0x82112a42) |
||
| 12345 |
mstore(0x20, 0x80) |
||
| 12346 |
mstore(0x40, p1) |
||
| 12347 |
mstore(0x60, p2) |
||
| 12348 |
mstore(0x80, p3) |
||
| 12349 |
writeString(0xa0, p0) |
||
| 12350 |
} |
||
| 12351 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12352 |
/// @solidity memory-safe-assembly |
||
| 12353 |
assembly {
|
||
| 12354 |
mstore(0x00, m0) |
||
| 12355 |
mstore(0x20, m1) |
||
| 12356 |
mstore(0x40, m2) |
||
| 12357 |
mstore(0x60, m3) |
||
| 12358 |
mstore(0x80, m4) |
||
| 12359 |
mstore(0xa0, m5) |
||
| 12360 |
mstore(0xc0, m6) |
||
| 12361 |
} |
||
| 12362 |
} |
||
| 12363 | |||
| 12364 |
function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure {
|
||
| 12365 |
bytes32 m0; |
||
| 12366 |
bytes32 m1; |
||
| 12367 |
bytes32 m2; |
||
| 12368 |
bytes32 m3; |
||
| 12369 |
bytes32 m4; |
||
| 12370 |
bytes32 m5; |
||
| 12371 |
bytes32 m6; |
||
| 12372 |
/// @solidity memory-safe-assembly |
||
| 12373 |
assembly {
|
||
| 12374 |
function writeString(pos, w) {
|
||
| 12375 |
let length := 0 |
||
| 12376 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12377 |
mstore(pos, length) |
||
| 12378 |
let shift := sub(256, shl(3, length)) |
||
| 12379 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12380 |
} |
||
| 12381 |
m0 := mload(0x00) |
||
| 12382 |
m1 := mload(0x20) |
||
| 12383 |
m2 := mload(0x40) |
||
| 12384 |
m3 := mload(0x60) |
||
| 12385 |
m4 := mload(0x80) |
||
| 12386 |
m5 := mload(0xa0) |
||
| 12387 |
m6 := mload(0xc0) |
||
| 12388 |
// Selector of `log(string,uint256,address,uint256)`. |
||
| 12389 |
mstore(0x00, 0x4f04fdc6) |
||
| 12390 |
mstore(0x20, 0x80) |
||
| 12391 |
mstore(0x40, p1) |
||
| 12392 |
mstore(0x60, p2) |
||
| 12393 |
mstore(0x80, p3) |
||
| 12394 |
writeString(0xa0, p0) |
||
| 12395 |
} |
||
| 12396 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12397 |
/// @solidity memory-safe-assembly |
||
| 12398 |
assembly {
|
||
| 12399 |
mstore(0x00, m0) |
||
| 12400 |
mstore(0x20, m1) |
||
| 12401 |
mstore(0x40, m2) |
||
| 12402 |
mstore(0x60, m3) |
||
| 12403 |
mstore(0x80, m4) |
||
| 12404 |
mstore(0xa0, m5) |
||
| 12405 |
mstore(0xc0, m6) |
||
| 12406 |
} |
||
| 12407 |
} |
||
| 12408 | |||
| 12409 |
function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure {
|
||
| 12410 |
bytes32 m0; |
||
| 12411 |
bytes32 m1; |
||
| 12412 |
bytes32 m2; |
||
| 12413 |
bytes32 m3; |
||
| 12414 |
bytes32 m4; |
||
| 12415 |
bytes32 m5; |
||
| 12416 |
bytes32 m6; |
||
| 12417 |
bytes32 m7; |
||
| 12418 |
bytes32 m8; |
||
| 12419 |
/// @solidity memory-safe-assembly |
||
| 12420 |
assembly {
|
||
| 12421 |
function writeString(pos, w) {
|
||
| 12422 |
let length := 0 |
||
| 12423 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12424 |
mstore(pos, length) |
||
| 12425 |
let shift := sub(256, shl(3, length)) |
||
| 12426 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12427 |
} |
||
| 12428 |
m0 := mload(0x00) |
||
| 12429 |
m1 := mload(0x20) |
||
| 12430 |
m2 := mload(0x40) |
||
| 12431 |
m3 := mload(0x60) |
||
| 12432 |
m4 := mload(0x80) |
||
| 12433 |
m5 := mload(0xa0) |
||
| 12434 |
m6 := mload(0xc0) |
||
| 12435 |
m7 := mload(0xe0) |
||
| 12436 |
m8 := mload(0x100) |
||
| 12437 |
// Selector of `log(string,uint256,address,string)`. |
||
| 12438 |
mstore(0x00, 0x9ffb2f93) |
||
| 12439 |
mstore(0x20, 0x80) |
||
| 12440 |
mstore(0x40, p1) |
||
| 12441 |
mstore(0x60, p2) |
||
| 12442 |
mstore(0x80, 0xc0) |
||
| 12443 |
writeString(0xa0, p0) |
||
| 12444 |
writeString(0xe0, p3) |
||
| 12445 |
} |
||
| 12446 |
_sendLogPayload(0x1c, 0x104); |
||
| 12447 |
/// @solidity memory-safe-assembly |
||
| 12448 |
assembly {
|
||
| 12449 |
mstore(0x00, m0) |
||
| 12450 |
mstore(0x20, m1) |
||
| 12451 |
mstore(0x40, m2) |
||
| 12452 |
mstore(0x60, m3) |
||
| 12453 |
mstore(0x80, m4) |
||
| 12454 |
mstore(0xa0, m5) |
||
| 12455 |
mstore(0xc0, m6) |
||
| 12456 |
mstore(0xe0, m7) |
||
| 12457 |
mstore(0x100, m8) |
||
| 12458 |
} |
||
| 12459 |
} |
||
| 12460 | |||
| 12461 |
function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure {
|
||
| 12462 |
bytes32 m0; |
||
| 12463 |
bytes32 m1; |
||
| 12464 |
bytes32 m2; |
||
| 12465 |
bytes32 m3; |
||
| 12466 |
bytes32 m4; |
||
| 12467 |
bytes32 m5; |
||
| 12468 |
bytes32 m6; |
||
| 12469 |
/// @solidity memory-safe-assembly |
||
| 12470 |
assembly {
|
||
| 12471 |
function writeString(pos, w) {
|
||
| 12472 |
let length := 0 |
||
| 12473 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12474 |
mstore(pos, length) |
||
| 12475 |
let shift := sub(256, shl(3, length)) |
||
| 12476 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12477 |
} |
||
| 12478 |
m0 := mload(0x00) |
||
| 12479 |
m1 := mload(0x20) |
||
| 12480 |
m2 := mload(0x40) |
||
| 12481 |
m3 := mload(0x60) |
||
| 12482 |
m4 := mload(0x80) |
||
| 12483 |
m5 := mload(0xa0) |
||
| 12484 |
m6 := mload(0xc0) |
||
| 12485 |
// Selector of `log(string,uint256,bool,address)`. |
||
| 12486 |
mstore(0x00, 0xe0e95b98) |
||
| 12487 |
mstore(0x20, 0x80) |
||
| 12488 |
mstore(0x40, p1) |
||
| 12489 |
mstore(0x60, p2) |
||
| 12490 |
mstore(0x80, p3) |
||
| 12491 |
writeString(0xa0, p0) |
||
| 12492 |
} |
||
| 12493 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12494 |
/// @solidity memory-safe-assembly |
||
| 12495 |
assembly {
|
||
| 12496 |
mstore(0x00, m0) |
||
| 12497 |
mstore(0x20, m1) |
||
| 12498 |
mstore(0x40, m2) |
||
| 12499 |
mstore(0x60, m3) |
||
| 12500 |
mstore(0x80, m4) |
||
| 12501 |
mstore(0xa0, m5) |
||
| 12502 |
mstore(0xc0, m6) |
||
| 12503 |
} |
||
| 12504 |
} |
||
| 12505 | |||
| 12506 |
function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure {
|
||
| 12507 |
bytes32 m0; |
||
| 12508 |
bytes32 m1; |
||
| 12509 |
bytes32 m2; |
||
| 12510 |
bytes32 m3; |
||
| 12511 |
bytes32 m4; |
||
| 12512 |
bytes32 m5; |
||
| 12513 |
bytes32 m6; |
||
| 12514 |
/// @solidity memory-safe-assembly |
||
| 12515 |
assembly {
|
||
| 12516 |
function writeString(pos, w) {
|
||
| 12517 |
let length := 0 |
||
| 12518 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12519 |
mstore(pos, length) |
||
| 12520 |
let shift := sub(256, shl(3, length)) |
||
| 12521 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12522 |
} |
||
| 12523 |
m0 := mload(0x00) |
||
| 12524 |
m1 := mload(0x20) |
||
| 12525 |
m2 := mload(0x40) |
||
| 12526 |
m3 := mload(0x60) |
||
| 12527 |
m4 := mload(0x80) |
||
| 12528 |
m5 := mload(0xa0) |
||
| 12529 |
m6 := mload(0xc0) |
||
| 12530 |
// Selector of `log(string,uint256,bool,bool)`. |
||
| 12531 |
mstore(0x00, 0x354c36d6) |
||
| 12532 |
mstore(0x20, 0x80) |
||
| 12533 |
mstore(0x40, p1) |
||
| 12534 |
mstore(0x60, p2) |
||
| 12535 |
mstore(0x80, p3) |
||
| 12536 |
writeString(0xa0, p0) |
||
| 12537 |
} |
||
| 12538 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12539 |
/// @solidity memory-safe-assembly |
||
| 12540 |
assembly {
|
||
| 12541 |
mstore(0x00, m0) |
||
| 12542 |
mstore(0x20, m1) |
||
| 12543 |
mstore(0x40, m2) |
||
| 12544 |
mstore(0x60, m3) |
||
| 12545 |
mstore(0x80, m4) |
||
| 12546 |
mstore(0xa0, m5) |
||
| 12547 |
mstore(0xc0, m6) |
||
| 12548 |
} |
||
| 12549 |
} |
||
| 12550 | |||
| 12551 |
function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure {
|
||
| 12552 |
bytes32 m0; |
||
| 12553 |
bytes32 m1; |
||
| 12554 |
bytes32 m2; |
||
| 12555 |
bytes32 m3; |
||
| 12556 |
bytes32 m4; |
||
| 12557 |
bytes32 m5; |
||
| 12558 |
bytes32 m6; |
||
| 12559 |
/// @solidity memory-safe-assembly |
||
| 12560 |
assembly {
|
||
| 12561 |
function writeString(pos, w) {
|
||
| 12562 |
let length := 0 |
||
| 12563 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12564 |
mstore(pos, length) |
||
| 12565 |
let shift := sub(256, shl(3, length)) |
||
| 12566 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12567 |
} |
||
| 12568 |
m0 := mload(0x00) |
||
| 12569 |
m1 := mload(0x20) |
||
| 12570 |
m2 := mload(0x40) |
||
| 12571 |
m3 := mload(0x60) |
||
| 12572 |
m4 := mload(0x80) |
||
| 12573 |
m5 := mload(0xa0) |
||
| 12574 |
m6 := mload(0xc0) |
||
| 12575 |
// Selector of `log(string,uint256,bool,uint256)`. |
||
| 12576 |
mstore(0x00, 0xe41b6f6f) |
||
| 12577 |
mstore(0x20, 0x80) |
||
| 12578 |
mstore(0x40, p1) |
||
| 12579 |
mstore(0x60, p2) |
||
| 12580 |
mstore(0x80, p3) |
||
| 12581 |
writeString(0xa0, p0) |
||
| 12582 |
} |
||
| 12583 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12584 |
/// @solidity memory-safe-assembly |
||
| 12585 |
assembly {
|
||
| 12586 |
mstore(0x00, m0) |
||
| 12587 |
mstore(0x20, m1) |
||
| 12588 |
mstore(0x40, m2) |
||
| 12589 |
mstore(0x60, m3) |
||
| 12590 |
mstore(0x80, m4) |
||
| 12591 |
mstore(0xa0, m5) |
||
| 12592 |
mstore(0xc0, m6) |
||
| 12593 |
} |
||
| 12594 |
} |
||
| 12595 | |||
| 12596 |
function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
|
||
| 12597 |
bytes32 m0; |
||
| 12598 |
bytes32 m1; |
||
| 12599 |
bytes32 m2; |
||
| 12600 |
bytes32 m3; |
||
| 12601 |
bytes32 m4; |
||
| 12602 |
bytes32 m5; |
||
| 12603 |
bytes32 m6; |
||
| 12604 |
bytes32 m7; |
||
| 12605 |
bytes32 m8; |
||
| 12606 |
/// @solidity memory-safe-assembly |
||
| 12607 |
assembly {
|
||
| 12608 |
function writeString(pos, w) {
|
||
| 12609 |
let length := 0 |
||
| 12610 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12611 |
mstore(pos, length) |
||
| 12612 |
let shift := sub(256, shl(3, length)) |
||
| 12613 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12614 |
} |
||
| 12615 |
m0 := mload(0x00) |
||
| 12616 |
m1 := mload(0x20) |
||
| 12617 |
m2 := mload(0x40) |
||
| 12618 |
m3 := mload(0x60) |
||
| 12619 |
m4 := mload(0x80) |
||
| 12620 |
m5 := mload(0xa0) |
||
| 12621 |
m6 := mload(0xc0) |
||
| 12622 |
m7 := mload(0xe0) |
||
| 12623 |
m8 := mload(0x100) |
||
| 12624 |
// Selector of `log(string,uint256,bool,string)`. |
||
| 12625 |
mstore(0x00, 0xabf73a98) |
||
| 12626 |
mstore(0x20, 0x80) |
||
| 12627 |
mstore(0x40, p1) |
||
| 12628 |
mstore(0x60, p2) |
||
| 12629 |
mstore(0x80, 0xc0) |
||
| 12630 |
writeString(0xa0, p0) |
||
| 12631 |
writeString(0xe0, p3) |
||
| 12632 |
} |
||
| 12633 |
_sendLogPayload(0x1c, 0x104); |
||
| 12634 |
/// @solidity memory-safe-assembly |
||
| 12635 |
assembly {
|
||
| 12636 |
mstore(0x00, m0) |
||
| 12637 |
mstore(0x20, m1) |
||
| 12638 |
mstore(0x40, m2) |
||
| 12639 |
mstore(0x60, m3) |
||
| 12640 |
mstore(0x80, m4) |
||
| 12641 |
mstore(0xa0, m5) |
||
| 12642 |
mstore(0xc0, m6) |
||
| 12643 |
mstore(0xe0, m7) |
||
| 12644 |
mstore(0x100, m8) |
||
| 12645 |
} |
||
| 12646 |
} |
||
| 12647 | |||
| 12648 |
function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure {
|
||
| 12649 |
bytes32 m0; |
||
| 12650 |
bytes32 m1; |
||
| 12651 |
bytes32 m2; |
||
| 12652 |
bytes32 m3; |
||
| 12653 |
bytes32 m4; |
||
| 12654 |
bytes32 m5; |
||
| 12655 |
bytes32 m6; |
||
| 12656 |
/// @solidity memory-safe-assembly |
||
| 12657 |
assembly {
|
||
| 12658 |
function writeString(pos, w) {
|
||
| 12659 |
let length := 0 |
||
| 12660 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12661 |
mstore(pos, length) |
||
| 12662 |
let shift := sub(256, shl(3, length)) |
||
| 12663 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12664 |
} |
||
| 12665 |
m0 := mload(0x00) |
||
| 12666 |
m1 := mload(0x20) |
||
| 12667 |
m2 := mload(0x40) |
||
| 12668 |
m3 := mload(0x60) |
||
| 12669 |
m4 := mload(0x80) |
||
| 12670 |
m5 := mload(0xa0) |
||
| 12671 |
m6 := mload(0xc0) |
||
| 12672 |
// Selector of `log(string,uint256,uint256,address)`. |
||
| 12673 |
mstore(0x00, 0xe21de278) |
||
| 12674 |
mstore(0x20, 0x80) |
||
| 12675 |
mstore(0x40, p1) |
||
| 12676 |
mstore(0x60, p2) |
||
| 12677 |
mstore(0x80, p3) |
||
| 12678 |
writeString(0xa0, p0) |
||
| 12679 |
} |
||
| 12680 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12681 |
/// @solidity memory-safe-assembly |
||
| 12682 |
assembly {
|
||
| 12683 |
mstore(0x00, m0) |
||
| 12684 |
mstore(0x20, m1) |
||
| 12685 |
mstore(0x40, m2) |
||
| 12686 |
mstore(0x60, m3) |
||
| 12687 |
mstore(0x80, m4) |
||
| 12688 |
mstore(0xa0, m5) |
||
| 12689 |
mstore(0xc0, m6) |
||
| 12690 |
} |
||
| 12691 |
} |
||
| 12692 | |||
| 12693 |
function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure {
|
||
| 12694 |
bytes32 m0; |
||
| 12695 |
bytes32 m1; |
||
| 12696 |
bytes32 m2; |
||
| 12697 |
bytes32 m3; |
||
| 12698 |
bytes32 m4; |
||
| 12699 |
bytes32 m5; |
||
| 12700 |
bytes32 m6; |
||
| 12701 |
/// @solidity memory-safe-assembly |
||
| 12702 |
assembly {
|
||
| 12703 |
function writeString(pos, w) {
|
||
| 12704 |
let length := 0 |
||
| 12705 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12706 |
mstore(pos, length) |
||
| 12707 |
let shift := sub(256, shl(3, length)) |
||
| 12708 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12709 |
} |
||
| 12710 |
m0 := mload(0x00) |
||
| 12711 |
m1 := mload(0x20) |
||
| 12712 |
m2 := mload(0x40) |
||
| 12713 |
m3 := mload(0x60) |
||
| 12714 |
m4 := mload(0x80) |
||
| 12715 |
m5 := mload(0xa0) |
||
| 12716 |
m6 := mload(0xc0) |
||
| 12717 |
// Selector of `log(string,uint256,uint256,bool)`. |
||
| 12718 |
mstore(0x00, 0x7626db92) |
||
| 12719 |
mstore(0x20, 0x80) |
||
| 12720 |
mstore(0x40, p1) |
||
| 12721 |
mstore(0x60, p2) |
||
| 12722 |
mstore(0x80, p3) |
||
| 12723 |
writeString(0xa0, p0) |
||
| 12724 |
} |
||
| 12725 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12726 |
/// @solidity memory-safe-assembly |
||
| 12727 |
assembly {
|
||
| 12728 |
mstore(0x00, m0) |
||
| 12729 |
mstore(0x20, m1) |
||
| 12730 |
mstore(0x40, m2) |
||
| 12731 |
mstore(0x60, m3) |
||
| 12732 |
mstore(0x80, m4) |
||
| 12733 |
mstore(0xa0, m5) |
||
| 12734 |
mstore(0xc0, m6) |
||
| 12735 |
} |
||
| 12736 |
} |
||
| 12737 | |||
| 12738 |
function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 12739 |
bytes32 m0; |
||
| 12740 |
bytes32 m1; |
||
| 12741 |
bytes32 m2; |
||
| 12742 |
bytes32 m3; |
||
| 12743 |
bytes32 m4; |
||
| 12744 |
bytes32 m5; |
||
| 12745 |
bytes32 m6; |
||
| 12746 |
/// @solidity memory-safe-assembly |
||
| 12747 |
assembly {
|
||
| 12748 |
function writeString(pos, w) {
|
||
| 12749 |
let length := 0 |
||
| 12750 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12751 |
mstore(pos, length) |
||
| 12752 |
let shift := sub(256, shl(3, length)) |
||
| 12753 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12754 |
} |
||
| 12755 |
m0 := mload(0x00) |
||
| 12756 |
m1 := mload(0x20) |
||
| 12757 |
m2 := mload(0x40) |
||
| 12758 |
m3 := mload(0x60) |
||
| 12759 |
m4 := mload(0x80) |
||
| 12760 |
m5 := mload(0xa0) |
||
| 12761 |
m6 := mload(0xc0) |
||
| 12762 |
// Selector of `log(string,uint256,uint256,uint256)`. |
||
| 12763 |
mstore(0x00, 0xa7a87853) |
||
| 12764 |
mstore(0x20, 0x80) |
||
| 12765 |
mstore(0x40, p1) |
||
| 12766 |
mstore(0x60, p2) |
||
| 12767 |
mstore(0x80, p3) |
||
| 12768 |
writeString(0xa0, p0) |
||
| 12769 |
} |
||
| 12770 |
_sendLogPayload(0x1c, 0xc4); |
||
| 12771 |
/// @solidity memory-safe-assembly |
||
| 12772 |
assembly {
|
||
| 12773 |
mstore(0x00, m0) |
||
| 12774 |
mstore(0x20, m1) |
||
| 12775 |
mstore(0x40, m2) |
||
| 12776 |
mstore(0x60, m3) |
||
| 12777 |
mstore(0x80, m4) |
||
| 12778 |
mstore(0xa0, m5) |
||
| 12779 |
mstore(0xc0, m6) |
||
| 12780 |
} |
||
| 12781 |
} |
||
| 12782 | |||
| 12783 |
function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 12784 |
bytes32 m0; |
||
| 12785 |
bytes32 m1; |
||
| 12786 |
bytes32 m2; |
||
| 12787 |
bytes32 m3; |
||
| 12788 |
bytes32 m4; |
||
| 12789 |
bytes32 m5; |
||
| 12790 |
bytes32 m6; |
||
| 12791 |
bytes32 m7; |
||
| 12792 |
bytes32 m8; |
||
| 12793 |
/// @solidity memory-safe-assembly |
||
| 12794 |
assembly {
|
||
| 12795 |
function writeString(pos, w) {
|
||
| 12796 |
let length := 0 |
||
| 12797 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12798 |
mstore(pos, length) |
||
| 12799 |
let shift := sub(256, shl(3, length)) |
||
| 12800 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12801 |
} |
||
| 12802 |
m0 := mload(0x00) |
||
| 12803 |
m1 := mload(0x20) |
||
| 12804 |
m2 := mload(0x40) |
||
| 12805 |
m3 := mload(0x60) |
||
| 12806 |
m4 := mload(0x80) |
||
| 12807 |
m5 := mload(0xa0) |
||
| 12808 |
m6 := mload(0xc0) |
||
| 12809 |
m7 := mload(0xe0) |
||
| 12810 |
m8 := mload(0x100) |
||
| 12811 |
// Selector of `log(string,uint256,uint256,string)`. |
||
| 12812 |
mstore(0x00, 0x854b3496) |
||
| 12813 |
mstore(0x20, 0x80) |
||
| 12814 |
mstore(0x40, p1) |
||
| 12815 |
mstore(0x60, p2) |
||
| 12816 |
mstore(0x80, 0xc0) |
||
| 12817 |
writeString(0xa0, p0) |
||
| 12818 |
writeString(0xe0, p3) |
||
| 12819 |
} |
||
| 12820 |
_sendLogPayload(0x1c, 0x104); |
||
| 12821 |
/// @solidity memory-safe-assembly |
||
| 12822 |
assembly {
|
||
| 12823 |
mstore(0x00, m0) |
||
| 12824 |
mstore(0x20, m1) |
||
| 12825 |
mstore(0x40, m2) |
||
| 12826 |
mstore(0x60, m3) |
||
| 12827 |
mstore(0x80, m4) |
||
| 12828 |
mstore(0xa0, m5) |
||
| 12829 |
mstore(0xc0, m6) |
||
| 12830 |
mstore(0xe0, m7) |
||
| 12831 |
mstore(0x100, m8) |
||
| 12832 |
} |
||
| 12833 |
} |
||
| 12834 | |||
| 12835 |
function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure {
|
||
| 12836 |
bytes32 m0; |
||
| 12837 |
bytes32 m1; |
||
| 12838 |
bytes32 m2; |
||
| 12839 |
bytes32 m3; |
||
| 12840 |
bytes32 m4; |
||
| 12841 |
bytes32 m5; |
||
| 12842 |
bytes32 m6; |
||
| 12843 |
bytes32 m7; |
||
| 12844 |
bytes32 m8; |
||
| 12845 |
/// @solidity memory-safe-assembly |
||
| 12846 |
assembly {
|
||
| 12847 |
function writeString(pos, w) {
|
||
| 12848 |
let length := 0 |
||
| 12849 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12850 |
mstore(pos, length) |
||
| 12851 |
let shift := sub(256, shl(3, length)) |
||
| 12852 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12853 |
} |
||
| 12854 |
m0 := mload(0x00) |
||
| 12855 |
m1 := mload(0x20) |
||
| 12856 |
m2 := mload(0x40) |
||
| 12857 |
m3 := mload(0x60) |
||
| 12858 |
m4 := mload(0x80) |
||
| 12859 |
m5 := mload(0xa0) |
||
| 12860 |
m6 := mload(0xc0) |
||
| 12861 |
m7 := mload(0xe0) |
||
| 12862 |
m8 := mload(0x100) |
||
| 12863 |
// Selector of `log(string,uint256,string,address)`. |
||
| 12864 |
mstore(0x00, 0x7c4632a4) |
||
| 12865 |
mstore(0x20, 0x80) |
||
| 12866 |
mstore(0x40, p1) |
||
| 12867 |
mstore(0x60, 0xc0) |
||
| 12868 |
mstore(0x80, p3) |
||
| 12869 |
writeString(0xa0, p0) |
||
| 12870 |
writeString(0xe0, p2) |
||
| 12871 |
} |
||
| 12872 |
_sendLogPayload(0x1c, 0x104); |
||
| 12873 |
/// @solidity memory-safe-assembly |
||
| 12874 |
assembly {
|
||
| 12875 |
mstore(0x00, m0) |
||
| 12876 |
mstore(0x20, m1) |
||
| 12877 |
mstore(0x40, m2) |
||
| 12878 |
mstore(0x60, m3) |
||
| 12879 |
mstore(0x80, m4) |
||
| 12880 |
mstore(0xa0, m5) |
||
| 12881 |
mstore(0xc0, m6) |
||
| 12882 |
mstore(0xe0, m7) |
||
| 12883 |
mstore(0x100, m8) |
||
| 12884 |
} |
||
| 12885 |
} |
||
| 12886 | |||
| 12887 |
function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
|
||
| 12888 |
bytes32 m0; |
||
| 12889 |
bytes32 m1; |
||
| 12890 |
bytes32 m2; |
||
| 12891 |
bytes32 m3; |
||
| 12892 |
bytes32 m4; |
||
| 12893 |
bytes32 m5; |
||
| 12894 |
bytes32 m6; |
||
| 12895 |
bytes32 m7; |
||
| 12896 |
bytes32 m8; |
||
| 12897 |
/// @solidity memory-safe-assembly |
||
| 12898 |
assembly {
|
||
| 12899 |
function writeString(pos, w) {
|
||
| 12900 |
let length := 0 |
||
| 12901 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12902 |
mstore(pos, length) |
||
| 12903 |
let shift := sub(256, shl(3, length)) |
||
| 12904 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12905 |
} |
||
| 12906 |
m0 := mload(0x00) |
||
| 12907 |
m1 := mload(0x20) |
||
| 12908 |
m2 := mload(0x40) |
||
| 12909 |
m3 := mload(0x60) |
||
| 12910 |
m4 := mload(0x80) |
||
| 12911 |
m5 := mload(0xa0) |
||
| 12912 |
m6 := mload(0xc0) |
||
| 12913 |
m7 := mload(0xe0) |
||
| 12914 |
m8 := mload(0x100) |
||
| 12915 |
// Selector of `log(string,uint256,string,bool)`. |
||
| 12916 |
mstore(0x00, 0x7d24491d) |
||
| 12917 |
mstore(0x20, 0x80) |
||
| 12918 |
mstore(0x40, p1) |
||
| 12919 |
mstore(0x60, 0xc0) |
||
| 12920 |
mstore(0x80, p3) |
||
| 12921 |
writeString(0xa0, p0) |
||
| 12922 |
writeString(0xe0, p2) |
||
| 12923 |
} |
||
| 12924 |
_sendLogPayload(0x1c, 0x104); |
||
| 12925 |
/// @solidity memory-safe-assembly |
||
| 12926 |
assembly {
|
||
| 12927 |
mstore(0x00, m0) |
||
| 12928 |
mstore(0x20, m1) |
||
| 12929 |
mstore(0x40, m2) |
||
| 12930 |
mstore(0x60, m3) |
||
| 12931 |
mstore(0x80, m4) |
||
| 12932 |
mstore(0xa0, m5) |
||
| 12933 |
mstore(0xc0, m6) |
||
| 12934 |
mstore(0xe0, m7) |
||
| 12935 |
mstore(0x100, m8) |
||
| 12936 |
} |
||
| 12937 |
} |
||
| 12938 | |||
| 12939 |
function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 12940 |
bytes32 m0; |
||
| 12941 |
bytes32 m1; |
||
| 12942 |
bytes32 m2; |
||
| 12943 |
bytes32 m3; |
||
| 12944 |
bytes32 m4; |
||
| 12945 |
bytes32 m5; |
||
| 12946 |
bytes32 m6; |
||
| 12947 |
bytes32 m7; |
||
| 12948 |
bytes32 m8; |
||
| 12949 |
/// @solidity memory-safe-assembly |
||
| 12950 |
assembly {
|
||
| 12951 |
function writeString(pos, w) {
|
||
| 12952 |
let length := 0 |
||
| 12953 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 12954 |
mstore(pos, length) |
||
| 12955 |
let shift := sub(256, shl(3, length)) |
||
| 12956 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 12957 |
} |
||
| 12958 |
m0 := mload(0x00) |
||
| 12959 |
m1 := mload(0x20) |
||
| 12960 |
m2 := mload(0x40) |
||
| 12961 |
m3 := mload(0x60) |
||
| 12962 |
m4 := mload(0x80) |
||
| 12963 |
m5 := mload(0xa0) |
||
| 12964 |
m6 := mload(0xc0) |
||
| 12965 |
m7 := mload(0xe0) |
||
| 12966 |
m8 := mload(0x100) |
||
| 12967 |
// Selector of `log(string,uint256,string,uint256)`. |
||
| 12968 |
mstore(0x00, 0xc67ea9d1) |
||
| 12969 |
mstore(0x20, 0x80) |
||
| 12970 |
mstore(0x40, p1) |
||
| 12971 |
mstore(0x60, 0xc0) |
||
| 12972 |
mstore(0x80, p3) |
||
| 12973 |
writeString(0xa0, p0) |
||
| 12974 |
writeString(0xe0, p2) |
||
| 12975 |
} |
||
| 12976 |
_sendLogPayload(0x1c, 0x104); |
||
| 12977 |
/// @solidity memory-safe-assembly |
||
| 12978 |
assembly {
|
||
| 12979 |
mstore(0x00, m0) |
||
| 12980 |
mstore(0x20, m1) |
||
| 12981 |
mstore(0x40, m2) |
||
| 12982 |
mstore(0x60, m3) |
||
| 12983 |
mstore(0x80, m4) |
||
| 12984 |
mstore(0xa0, m5) |
||
| 12985 |
mstore(0xc0, m6) |
||
| 12986 |
mstore(0xe0, m7) |
||
| 12987 |
mstore(0x100, m8) |
||
| 12988 |
} |
||
| 12989 |
} |
||
| 12990 | |||
| 12991 |
function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 12992 |
bytes32 m0; |
||
| 12993 |
bytes32 m1; |
||
| 12994 |
bytes32 m2; |
||
| 12995 |
bytes32 m3; |
||
| 12996 |
bytes32 m4; |
||
| 12997 |
bytes32 m5; |
||
| 12998 |
bytes32 m6; |
||
| 12999 |
bytes32 m7; |
||
| 13000 |
bytes32 m8; |
||
| 13001 |
bytes32 m9; |
||
| 13002 |
bytes32 m10; |
||
| 13003 |
/// @solidity memory-safe-assembly |
||
| 13004 |
assembly {
|
||
| 13005 |
function writeString(pos, w) {
|
||
| 13006 |
let length := 0 |
||
| 13007 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13008 |
mstore(pos, length) |
||
| 13009 |
let shift := sub(256, shl(3, length)) |
||
| 13010 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13011 |
} |
||
| 13012 |
m0 := mload(0x00) |
||
| 13013 |
m1 := mload(0x20) |
||
| 13014 |
m2 := mload(0x40) |
||
| 13015 |
m3 := mload(0x60) |
||
| 13016 |
m4 := mload(0x80) |
||
| 13017 |
m5 := mload(0xa0) |
||
| 13018 |
m6 := mload(0xc0) |
||
| 13019 |
m7 := mload(0xe0) |
||
| 13020 |
m8 := mload(0x100) |
||
| 13021 |
m9 := mload(0x120) |
||
| 13022 |
m10 := mload(0x140) |
||
| 13023 |
// Selector of `log(string,uint256,string,string)`. |
||
| 13024 |
mstore(0x00, 0x5ab84e1f) |
||
| 13025 |
mstore(0x20, 0x80) |
||
| 13026 |
mstore(0x40, p1) |
||
| 13027 |
mstore(0x60, 0xc0) |
||
| 13028 |
mstore(0x80, 0x100) |
||
| 13029 |
writeString(0xa0, p0) |
||
| 13030 |
writeString(0xe0, p2) |
||
| 13031 |
writeString(0x120, p3) |
||
| 13032 |
} |
||
| 13033 |
_sendLogPayload(0x1c, 0x144); |
||
| 13034 |
/// @solidity memory-safe-assembly |
||
| 13035 |
assembly {
|
||
| 13036 |
mstore(0x00, m0) |
||
| 13037 |
mstore(0x20, m1) |
||
| 13038 |
mstore(0x40, m2) |
||
| 13039 |
mstore(0x60, m3) |
||
| 13040 |
mstore(0x80, m4) |
||
| 13041 |
mstore(0xa0, m5) |
||
| 13042 |
mstore(0xc0, m6) |
||
| 13043 |
mstore(0xe0, m7) |
||
| 13044 |
mstore(0x100, m8) |
||
| 13045 |
mstore(0x120, m9) |
||
| 13046 |
mstore(0x140, m10) |
||
| 13047 |
} |
||
| 13048 |
} |
||
| 13049 | |||
| 13050 |
function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure {
|
||
| 13051 |
bytes32 m0; |
||
| 13052 |
bytes32 m1; |
||
| 13053 |
bytes32 m2; |
||
| 13054 |
bytes32 m3; |
||
| 13055 |
bytes32 m4; |
||
| 13056 |
bytes32 m5; |
||
| 13057 |
bytes32 m6; |
||
| 13058 |
bytes32 m7; |
||
| 13059 |
bytes32 m8; |
||
| 13060 |
/// @solidity memory-safe-assembly |
||
| 13061 |
assembly {
|
||
| 13062 |
function writeString(pos, w) {
|
||
| 13063 |
let length := 0 |
||
| 13064 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13065 |
mstore(pos, length) |
||
| 13066 |
let shift := sub(256, shl(3, length)) |
||
| 13067 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13068 |
} |
||
| 13069 |
m0 := mload(0x00) |
||
| 13070 |
m1 := mload(0x20) |
||
| 13071 |
m2 := mload(0x40) |
||
| 13072 |
m3 := mload(0x60) |
||
| 13073 |
m4 := mload(0x80) |
||
| 13074 |
m5 := mload(0xa0) |
||
| 13075 |
m6 := mload(0xc0) |
||
| 13076 |
m7 := mload(0xe0) |
||
| 13077 |
m8 := mload(0x100) |
||
| 13078 |
// Selector of `log(string,string,address,address)`. |
||
| 13079 |
mstore(0x00, 0x439c7bef) |
||
| 13080 |
mstore(0x20, 0x80) |
||
| 13081 |
mstore(0x40, 0xc0) |
||
| 13082 |
mstore(0x60, p2) |
||
| 13083 |
mstore(0x80, p3) |
||
| 13084 |
writeString(0xa0, p0) |
||
| 13085 |
writeString(0xe0, p1) |
||
| 13086 |
} |
||
| 13087 |
_sendLogPayload(0x1c, 0x104); |
||
| 13088 |
/// @solidity memory-safe-assembly |
||
| 13089 |
assembly {
|
||
| 13090 |
mstore(0x00, m0) |
||
| 13091 |
mstore(0x20, m1) |
||
| 13092 |
mstore(0x40, m2) |
||
| 13093 |
mstore(0x60, m3) |
||
| 13094 |
mstore(0x80, m4) |
||
| 13095 |
mstore(0xa0, m5) |
||
| 13096 |
mstore(0xc0, m6) |
||
| 13097 |
mstore(0xe0, m7) |
||
| 13098 |
mstore(0x100, m8) |
||
| 13099 |
} |
||
| 13100 |
} |
||
| 13101 | |||
| 13102 |
function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure {
|
||
| 13103 |
bytes32 m0; |
||
| 13104 |
bytes32 m1; |
||
| 13105 |
bytes32 m2; |
||
| 13106 |
bytes32 m3; |
||
| 13107 |
bytes32 m4; |
||
| 13108 |
bytes32 m5; |
||
| 13109 |
bytes32 m6; |
||
| 13110 |
bytes32 m7; |
||
| 13111 |
bytes32 m8; |
||
| 13112 |
/// @solidity memory-safe-assembly |
||
| 13113 |
assembly {
|
||
| 13114 |
function writeString(pos, w) {
|
||
| 13115 |
let length := 0 |
||
| 13116 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13117 |
mstore(pos, length) |
||
| 13118 |
let shift := sub(256, shl(3, length)) |
||
| 13119 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13120 |
} |
||
| 13121 |
m0 := mload(0x00) |
||
| 13122 |
m1 := mload(0x20) |
||
| 13123 |
m2 := mload(0x40) |
||
| 13124 |
m3 := mload(0x60) |
||
| 13125 |
m4 := mload(0x80) |
||
| 13126 |
m5 := mload(0xa0) |
||
| 13127 |
m6 := mload(0xc0) |
||
| 13128 |
m7 := mload(0xe0) |
||
| 13129 |
m8 := mload(0x100) |
||
| 13130 |
// Selector of `log(string,string,address,bool)`. |
||
| 13131 |
mstore(0x00, 0x5ccd4e37) |
||
| 13132 |
mstore(0x20, 0x80) |
||
| 13133 |
mstore(0x40, 0xc0) |
||
| 13134 |
mstore(0x60, p2) |
||
| 13135 |
mstore(0x80, p3) |
||
| 13136 |
writeString(0xa0, p0) |
||
| 13137 |
writeString(0xe0, p1) |
||
| 13138 |
} |
||
| 13139 |
_sendLogPayload(0x1c, 0x104); |
||
| 13140 |
/// @solidity memory-safe-assembly |
||
| 13141 |
assembly {
|
||
| 13142 |
mstore(0x00, m0) |
||
| 13143 |
mstore(0x20, m1) |
||
| 13144 |
mstore(0x40, m2) |
||
| 13145 |
mstore(0x60, m3) |
||
| 13146 |
mstore(0x80, m4) |
||
| 13147 |
mstore(0xa0, m5) |
||
| 13148 |
mstore(0xc0, m6) |
||
| 13149 |
mstore(0xe0, m7) |
||
| 13150 |
mstore(0x100, m8) |
||
| 13151 |
} |
||
| 13152 |
} |
||
| 13153 | |||
| 13154 |
function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure {
|
||
| 13155 |
bytes32 m0; |
||
| 13156 |
bytes32 m1; |
||
| 13157 |
bytes32 m2; |
||
| 13158 |
bytes32 m3; |
||
| 13159 |
bytes32 m4; |
||
| 13160 |
bytes32 m5; |
||
| 13161 |
bytes32 m6; |
||
| 13162 |
bytes32 m7; |
||
| 13163 |
bytes32 m8; |
||
| 13164 |
/// @solidity memory-safe-assembly |
||
| 13165 |
assembly {
|
||
| 13166 |
function writeString(pos, w) {
|
||
| 13167 |
let length := 0 |
||
| 13168 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13169 |
mstore(pos, length) |
||
| 13170 |
let shift := sub(256, shl(3, length)) |
||
| 13171 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13172 |
} |
||
| 13173 |
m0 := mload(0x00) |
||
| 13174 |
m1 := mload(0x20) |
||
| 13175 |
m2 := mload(0x40) |
||
| 13176 |
m3 := mload(0x60) |
||
| 13177 |
m4 := mload(0x80) |
||
| 13178 |
m5 := mload(0xa0) |
||
| 13179 |
m6 := mload(0xc0) |
||
| 13180 |
m7 := mload(0xe0) |
||
| 13181 |
m8 := mload(0x100) |
||
| 13182 |
// Selector of `log(string,string,address,uint256)`. |
||
| 13183 |
mstore(0x00, 0x7cc3c607) |
||
| 13184 |
mstore(0x20, 0x80) |
||
| 13185 |
mstore(0x40, 0xc0) |
||
| 13186 |
mstore(0x60, p2) |
||
| 13187 |
mstore(0x80, p3) |
||
| 13188 |
writeString(0xa0, p0) |
||
| 13189 |
writeString(0xe0, p1) |
||
| 13190 |
} |
||
| 13191 |
_sendLogPayload(0x1c, 0x104); |
||
| 13192 |
/// @solidity memory-safe-assembly |
||
| 13193 |
assembly {
|
||
| 13194 |
mstore(0x00, m0) |
||
| 13195 |
mstore(0x20, m1) |
||
| 13196 |
mstore(0x40, m2) |
||
| 13197 |
mstore(0x60, m3) |
||
| 13198 |
mstore(0x80, m4) |
||
| 13199 |
mstore(0xa0, m5) |
||
| 13200 |
mstore(0xc0, m6) |
||
| 13201 |
mstore(0xe0, m7) |
||
| 13202 |
mstore(0x100, m8) |
||
| 13203 |
} |
||
| 13204 |
} |
||
| 13205 | |||
| 13206 |
function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
|
||
| 13207 |
bytes32 m0; |
||
| 13208 |
bytes32 m1; |
||
| 13209 |
bytes32 m2; |
||
| 13210 |
bytes32 m3; |
||
| 13211 |
bytes32 m4; |
||
| 13212 |
bytes32 m5; |
||
| 13213 |
bytes32 m6; |
||
| 13214 |
bytes32 m7; |
||
| 13215 |
bytes32 m8; |
||
| 13216 |
bytes32 m9; |
||
| 13217 |
bytes32 m10; |
||
| 13218 |
/// @solidity memory-safe-assembly |
||
| 13219 |
assembly {
|
||
| 13220 |
function writeString(pos, w) {
|
||
| 13221 |
let length := 0 |
||
| 13222 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13223 |
mstore(pos, length) |
||
| 13224 |
let shift := sub(256, shl(3, length)) |
||
| 13225 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13226 |
} |
||
| 13227 |
m0 := mload(0x00) |
||
| 13228 |
m1 := mload(0x20) |
||
| 13229 |
m2 := mload(0x40) |
||
| 13230 |
m3 := mload(0x60) |
||
| 13231 |
m4 := mload(0x80) |
||
| 13232 |
m5 := mload(0xa0) |
||
| 13233 |
m6 := mload(0xc0) |
||
| 13234 |
m7 := mload(0xe0) |
||
| 13235 |
m8 := mload(0x100) |
||
| 13236 |
m9 := mload(0x120) |
||
| 13237 |
m10 := mload(0x140) |
||
| 13238 |
// Selector of `log(string,string,address,string)`. |
||
| 13239 |
mstore(0x00, 0xeb1bff80) |
||
| 13240 |
mstore(0x20, 0x80) |
||
| 13241 |
mstore(0x40, 0xc0) |
||
| 13242 |
mstore(0x60, p2) |
||
| 13243 |
mstore(0x80, 0x100) |
||
| 13244 |
writeString(0xa0, p0) |
||
| 13245 |
writeString(0xe0, p1) |
||
| 13246 |
writeString(0x120, p3) |
||
| 13247 |
} |
||
| 13248 |
_sendLogPayload(0x1c, 0x144); |
||
| 13249 |
/// @solidity memory-safe-assembly |
||
| 13250 |
assembly {
|
||
| 13251 |
mstore(0x00, m0) |
||
| 13252 |
mstore(0x20, m1) |
||
| 13253 |
mstore(0x40, m2) |
||
| 13254 |
mstore(0x60, m3) |
||
| 13255 |
mstore(0x80, m4) |
||
| 13256 |
mstore(0xa0, m5) |
||
| 13257 |
mstore(0xc0, m6) |
||
| 13258 |
mstore(0xe0, m7) |
||
| 13259 |
mstore(0x100, m8) |
||
| 13260 |
mstore(0x120, m9) |
||
| 13261 |
mstore(0x140, m10) |
||
| 13262 |
} |
||
| 13263 |
} |
||
| 13264 | |||
| 13265 |
function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure {
|
||
| 13266 |
bytes32 m0; |
||
| 13267 |
bytes32 m1; |
||
| 13268 |
bytes32 m2; |
||
| 13269 |
bytes32 m3; |
||
| 13270 |
bytes32 m4; |
||
| 13271 |
bytes32 m5; |
||
| 13272 |
bytes32 m6; |
||
| 13273 |
bytes32 m7; |
||
| 13274 |
bytes32 m8; |
||
| 13275 |
/// @solidity memory-safe-assembly |
||
| 13276 |
assembly {
|
||
| 13277 |
function writeString(pos, w) {
|
||
| 13278 |
let length := 0 |
||
| 13279 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13280 |
mstore(pos, length) |
||
| 13281 |
let shift := sub(256, shl(3, length)) |
||
| 13282 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13283 |
} |
||
| 13284 |
m0 := mload(0x00) |
||
| 13285 |
m1 := mload(0x20) |
||
| 13286 |
m2 := mload(0x40) |
||
| 13287 |
m3 := mload(0x60) |
||
| 13288 |
m4 := mload(0x80) |
||
| 13289 |
m5 := mload(0xa0) |
||
| 13290 |
m6 := mload(0xc0) |
||
| 13291 |
m7 := mload(0xe0) |
||
| 13292 |
m8 := mload(0x100) |
||
| 13293 |
// Selector of `log(string,string,bool,address)`. |
||
| 13294 |
mstore(0x00, 0xc371c7db) |
||
| 13295 |
mstore(0x20, 0x80) |
||
| 13296 |
mstore(0x40, 0xc0) |
||
| 13297 |
mstore(0x60, p2) |
||
| 13298 |
mstore(0x80, p3) |
||
| 13299 |
writeString(0xa0, p0) |
||
| 13300 |
writeString(0xe0, p1) |
||
| 13301 |
} |
||
| 13302 |
_sendLogPayload(0x1c, 0x104); |
||
| 13303 |
/// @solidity memory-safe-assembly |
||
| 13304 |
assembly {
|
||
| 13305 |
mstore(0x00, m0) |
||
| 13306 |
mstore(0x20, m1) |
||
| 13307 |
mstore(0x40, m2) |
||
| 13308 |
mstore(0x60, m3) |
||
| 13309 |
mstore(0x80, m4) |
||
| 13310 |
mstore(0xa0, m5) |
||
| 13311 |
mstore(0xc0, m6) |
||
| 13312 |
mstore(0xe0, m7) |
||
| 13313 |
mstore(0x100, m8) |
||
| 13314 |
} |
||
| 13315 |
} |
||
| 13316 | |||
| 13317 |
function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure {
|
||
| 13318 |
bytes32 m0; |
||
| 13319 |
bytes32 m1; |
||
| 13320 |
bytes32 m2; |
||
| 13321 |
bytes32 m3; |
||
| 13322 |
bytes32 m4; |
||
| 13323 |
bytes32 m5; |
||
| 13324 |
bytes32 m6; |
||
| 13325 |
bytes32 m7; |
||
| 13326 |
bytes32 m8; |
||
| 13327 |
/// @solidity memory-safe-assembly |
||
| 13328 |
assembly {
|
||
| 13329 |
function writeString(pos, w) {
|
||
| 13330 |
let length := 0 |
||
| 13331 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13332 |
mstore(pos, length) |
||
| 13333 |
let shift := sub(256, shl(3, length)) |
||
| 13334 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13335 |
} |
||
| 13336 |
m0 := mload(0x00) |
||
| 13337 |
m1 := mload(0x20) |
||
| 13338 |
m2 := mload(0x40) |
||
| 13339 |
m3 := mload(0x60) |
||
| 13340 |
m4 := mload(0x80) |
||
| 13341 |
m5 := mload(0xa0) |
||
| 13342 |
m6 := mload(0xc0) |
||
| 13343 |
m7 := mload(0xe0) |
||
| 13344 |
m8 := mload(0x100) |
||
| 13345 |
// Selector of `log(string,string,bool,bool)`. |
||
| 13346 |
mstore(0x00, 0x40785869) |
||
| 13347 |
mstore(0x20, 0x80) |
||
| 13348 |
mstore(0x40, 0xc0) |
||
| 13349 |
mstore(0x60, p2) |
||
| 13350 |
mstore(0x80, p3) |
||
| 13351 |
writeString(0xa0, p0) |
||
| 13352 |
writeString(0xe0, p1) |
||
| 13353 |
} |
||
| 13354 |
_sendLogPayload(0x1c, 0x104); |
||
| 13355 |
/// @solidity memory-safe-assembly |
||
| 13356 |
assembly {
|
||
| 13357 |
mstore(0x00, m0) |
||
| 13358 |
mstore(0x20, m1) |
||
| 13359 |
mstore(0x40, m2) |
||
| 13360 |
mstore(0x60, m3) |
||
| 13361 |
mstore(0x80, m4) |
||
| 13362 |
mstore(0xa0, m5) |
||
| 13363 |
mstore(0xc0, m6) |
||
| 13364 |
mstore(0xe0, m7) |
||
| 13365 |
mstore(0x100, m8) |
||
| 13366 |
} |
||
| 13367 |
} |
||
| 13368 | |||
| 13369 |
function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
|
||
| 13370 |
bytes32 m0; |
||
| 13371 |
bytes32 m1; |
||
| 13372 |
bytes32 m2; |
||
| 13373 |
bytes32 m3; |
||
| 13374 |
bytes32 m4; |
||
| 13375 |
bytes32 m5; |
||
| 13376 |
bytes32 m6; |
||
| 13377 |
bytes32 m7; |
||
| 13378 |
bytes32 m8; |
||
| 13379 |
/// @solidity memory-safe-assembly |
||
| 13380 |
assembly {
|
||
| 13381 |
function writeString(pos, w) {
|
||
| 13382 |
let length := 0 |
||
| 13383 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13384 |
mstore(pos, length) |
||
| 13385 |
let shift := sub(256, shl(3, length)) |
||
| 13386 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13387 |
} |
||
| 13388 |
m0 := mload(0x00) |
||
| 13389 |
m1 := mload(0x20) |
||
| 13390 |
m2 := mload(0x40) |
||
| 13391 |
m3 := mload(0x60) |
||
| 13392 |
m4 := mload(0x80) |
||
| 13393 |
m5 := mload(0xa0) |
||
| 13394 |
m6 := mload(0xc0) |
||
| 13395 |
m7 := mload(0xe0) |
||
| 13396 |
m8 := mload(0x100) |
||
| 13397 |
// Selector of `log(string,string,bool,uint256)`. |
||
| 13398 |
mstore(0x00, 0xd6aefad2) |
||
| 13399 |
mstore(0x20, 0x80) |
||
| 13400 |
mstore(0x40, 0xc0) |
||
| 13401 |
mstore(0x60, p2) |
||
| 13402 |
mstore(0x80, p3) |
||
| 13403 |
writeString(0xa0, p0) |
||
| 13404 |
writeString(0xe0, p1) |
||
| 13405 |
} |
||
| 13406 |
_sendLogPayload(0x1c, 0x104); |
||
| 13407 |
/// @solidity memory-safe-assembly |
||
| 13408 |
assembly {
|
||
| 13409 |
mstore(0x00, m0) |
||
| 13410 |
mstore(0x20, m1) |
||
| 13411 |
mstore(0x40, m2) |
||
| 13412 |
mstore(0x60, m3) |
||
| 13413 |
mstore(0x80, m4) |
||
| 13414 |
mstore(0xa0, m5) |
||
| 13415 |
mstore(0xc0, m6) |
||
| 13416 |
mstore(0xe0, m7) |
||
| 13417 |
mstore(0x100, m8) |
||
| 13418 |
} |
||
| 13419 |
} |
||
| 13420 | |||
| 13421 |
function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
|
||
| 13422 |
bytes32 m0; |
||
| 13423 |
bytes32 m1; |
||
| 13424 |
bytes32 m2; |
||
| 13425 |
bytes32 m3; |
||
| 13426 |
bytes32 m4; |
||
| 13427 |
bytes32 m5; |
||
| 13428 |
bytes32 m6; |
||
| 13429 |
bytes32 m7; |
||
| 13430 |
bytes32 m8; |
||
| 13431 |
bytes32 m9; |
||
| 13432 |
bytes32 m10; |
||
| 13433 |
/// @solidity memory-safe-assembly |
||
| 13434 |
assembly {
|
||
| 13435 |
function writeString(pos, w) {
|
||
| 13436 |
let length := 0 |
||
| 13437 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13438 |
mstore(pos, length) |
||
| 13439 |
let shift := sub(256, shl(3, length)) |
||
| 13440 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13441 |
} |
||
| 13442 |
m0 := mload(0x00) |
||
| 13443 |
m1 := mload(0x20) |
||
| 13444 |
m2 := mload(0x40) |
||
| 13445 |
m3 := mload(0x60) |
||
| 13446 |
m4 := mload(0x80) |
||
| 13447 |
m5 := mload(0xa0) |
||
| 13448 |
m6 := mload(0xc0) |
||
| 13449 |
m7 := mload(0xe0) |
||
| 13450 |
m8 := mload(0x100) |
||
| 13451 |
m9 := mload(0x120) |
||
| 13452 |
m10 := mload(0x140) |
||
| 13453 |
// Selector of `log(string,string,bool,string)`. |
||
| 13454 |
mstore(0x00, 0x5e84b0ea) |
||
| 13455 |
mstore(0x20, 0x80) |
||
| 13456 |
mstore(0x40, 0xc0) |
||
| 13457 |
mstore(0x60, p2) |
||
| 13458 |
mstore(0x80, 0x100) |
||
| 13459 |
writeString(0xa0, p0) |
||
| 13460 |
writeString(0xe0, p1) |
||
| 13461 |
writeString(0x120, p3) |
||
| 13462 |
} |
||
| 13463 |
_sendLogPayload(0x1c, 0x144); |
||
| 13464 |
/// @solidity memory-safe-assembly |
||
| 13465 |
assembly {
|
||
| 13466 |
mstore(0x00, m0) |
||
| 13467 |
mstore(0x20, m1) |
||
| 13468 |
mstore(0x40, m2) |
||
| 13469 |
mstore(0x60, m3) |
||
| 13470 |
mstore(0x80, m4) |
||
| 13471 |
mstore(0xa0, m5) |
||
| 13472 |
mstore(0xc0, m6) |
||
| 13473 |
mstore(0xe0, m7) |
||
| 13474 |
mstore(0x100, m8) |
||
| 13475 |
mstore(0x120, m9) |
||
| 13476 |
mstore(0x140, m10) |
||
| 13477 |
} |
||
| 13478 |
} |
||
| 13479 | |||
| 13480 |
function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure {
|
||
| 13481 |
bytes32 m0; |
||
| 13482 |
bytes32 m1; |
||
| 13483 |
bytes32 m2; |
||
| 13484 |
bytes32 m3; |
||
| 13485 |
bytes32 m4; |
||
| 13486 |
bytes32 m5; |
||
| 13487 |
bytes32 m6; |
||
| 13488 |
bytes32 m7; |
||
| 13489 |
bytes32 m8; |
||
| 13490 |
/// @solidity memory-safe-assembly |
||
| 13491 |
assembly {
|
||
| 13492 |
function writeString(pos, w) {
|
||
| 13493 |
let length := 0 |
||
| 13494 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13495 |
mstore(pos, length) |
||
| 13496 |
let shift := sub(256, shl(3, length)) |
||
| 13497 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13498 |
} |
||
| 13499 |
m0 := mload(0x00) |
||
| 13500 |
m1 := mload(0x20) |
||
| 13501 |
m2 := mload(0x40) |
||
| 13502 |
m3 := mload(0x60) |
||
| 13503 |
m4 := mload(0x80) |
||
| 13504 |
m5 := mload(0xa0) |
||
| 13505 |
m6 := mload(0xc0) |
||
| 13506 |
m7 := mload(0xe0) |
||
| 13507 |
m8 := mload(0x100) |
||
| 13508 |
// Selector of `log(string,string,uint256,address)`. |
||
| 13509 |
mstore(0x00, 0x1023f7b2) |
||
| 13510 |
mstore(0x20, 0x80) |
||
| 13511 |
mstore(0x40, 0xc0) |
||
| 13512 |
mstore(0x60, p2) |
||
| 13513 |
mstore(0x80, p3) |
||
| 13514 |
writeString(0xa0, p0) |
||
| 13515 |
writeString(0xe0, p1) |
||
| 13516 |
} |
||
| 13517 |
_sendLogPayload(0x1c, 0x104); |
||
| 13518 |
/// @solidity memory-safe-assembly |
||
| 13519 |
assembly {
|
||
| 13520 |
mstore(0x00, m0) |
||
| 13521 |
mstore(0x20, m1) |
||
| 13522 |
mstore(0x40, m2) |
||
| 13523 |
mstore(0x60, m3) |
||
| 13524 |
mstore(0x80, m4) |
||
| 13525 |
mstore(0xa0, m5) |
||
| 13526 |
mstore(0xc0, m6) |
||
| 13527 |
mstore(0xe0, m7) |
||
| 13528 |
mstore(0x100, m8) |
||
| 13529 |
} |
||
| 13530 |
} |
||
| 13531 | |||
| 13532 |
function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
|
||
| 13533 |
bytes32 m0; |
||
| 13534 |
bytes32 m1; |
||
| 13535 |
bytes32 m2; |
||
| 13536 |
bytes32 m3; |
||
| 13537 |
bytes32 m4; |
||
| 13538 |
bytes32 m5; |
||
| 13539 |
bytes32 m6; |
||
| 13540 |
bytes32 m7; |
||
| 13541 |
bytes32 m8; |
||
| 13542 |
/// @solidity memory-safe-assembly |
||
| 13543 |
assembly {
|
||
| 13544 |
function writeString(pos, w) {
|
||
| 13545 |
let length := 0 |
||
| 13546 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13547 |
mstore(pos, length) |
||
| 13548 |
let shift := sub(256, shl(3, length)) |
||
| 13549 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13550 |
} |
||
| 13551 |
m0 := mload(0x00) |
||
| 13552 |
m1 := mload(0x20) |
||
| 13553 |
m2 := mload(0x40) |
||
| 13554 |
m3 := mload(0x60) |
||
| 13555 |
m4 := mload(0x80) |
||
| 13556 |
m5 := mload(0xa0) |
||
| 13557 |
m6 := mload(0xc0) |
||
| 13558 |
m7 := mload(0xe0) |
||
| 13559 |
m8 := mload(0x100) |
||
| 13560 |
// Selector of `log(string,string,uint256,bool)`. |
||
| 13561 |
mstore(0x00, 0xc3a8a654) |
||
| 13562 |
mstore(0x20, 0x80) |
||
| 13563 |
mstore(0x40, 0xc0) |
||
| 13564 |
mstore(0x60, p2) |
||
| 13565 |
mstore(0x80, p3) |
||
| 13566 |
writeString(0xa0, p0) |
||
| 13567 |
writeString(0xe0, p1) |
||
| 13568 |
} |
||
| 13569 |
_sendLogPayload(0x1c, 0x104); |
||
| 13570 |
/// @solidity memory-safe-assembly |
||
| 13571 |
assembly {
|
||
| 13572 |
mstore(0x00, m0) |
||
| 13573 |
mstore(0x20, m1) |
||
| 13574 |
mstore(0x40, m2) |
||
| 13575 |
mstore(0x60, m3) |
||
| 13576 |
mstore(0x80, m4) |
||
| 13577 |
mstore(0xa0, m5) |
||
| 13578 |
mstore(0xc0, m6) |
||
| 13579 |
mstore(0xe0, m7) |
||
| 13580 |
mstore(0x100, m8) |
||
| 13581 |
} |
||
| 13582 |
} |
||
| 13583 | |||
| 13584 |
function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
|
||
| 13585 |
bytes32 m0; |
||
| 13586 |
bytes32 m1; |
||
| 13587 |
bytes32 m2; |
||
| 13588 |
bytes32 m3; |
||
| 13589 |
bytes32 m4; |
||
| 13590 |
bytes32 m5; |
||
| 13591 |
bytes32 m6; |
||
| 13592 |
bytes32 m7; |
||
| 13593 |
bytes32 m8; |
||
| 13594 |
/// @solidity memory-safe-assembly |
||
| 13595 |
assembly {
|
||
| 13596 |
function writeString(pos, w) {
|
||
| 13597 |
let length := 0 |
||
| 13598 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13599 |
mstore(pos, length) |
||
| 13600 |
let shift := sub(256, shl(3, length)) |
||
| 13601 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13602 |
} |
||
| 13603 |
m0 := mload(0x00) |
||
| 13604 |
m1 := mload(0x20) |
||
| 13605 |
m2 := mload(0x40) |
||
| 13606 |
m3 := mload(0x60) |
||
| 13607 |
m4 := mload(0x80) |
||
| 13608 |
m5 := mload(0xa0) |
||
| 13609 |
m6 := mload(0xc0) |
||
| 13610 |
m7 := mload(0xe0) |
||
| 13611 |
m8 := mload(0x100) |
||
| 13612 |
// Selector of `log(string,string,uint256,uint256)`. |
||
| 13613 |
mstore(0x00, 0xf45d7d2c) |
||
| 13614 |
mstore(0x20, 0x80) |
||
| 13615 |
mstore(0x40, 0xc0) |
||
| 13616 |
mstore(0x60, p2) |
||
| 13617 |
mstore(0x80, p3) |
||
| 13618 |
writeString(0xa0, p0) |
||
| 13619 |
writeString(0xe0, p1) |
||
| 13620 |
} |
||
| 13621 |
_sendLogPayload(0x1c, 0x104); |
||
| 13622 |
/// @solidity memory-safe-assembly |
||
| 13623 |
assembly {
|
||
| 13624 |
mstore(0x00, m0) |
||
| 13625 |
mstore(0x20, m1) |
||
| 13626 |
mstore(0x40, m2) |
||
| 13627 |
mstore(0x60, m3) |
||
| 13628 |
mstore(0x80, m4) |
||
| 13629 |
mstore(0xa0, m5) |
||
| 13630 |
mstore(0xc0, m6) |
||
| 13631 |
mstore(0xe0, m7) |
||
| 13632 |
mstore(0x100, m8) |
||
| 13633 |
} |
||
| 13634 |
} |
||
| 13635 | |||
| 13636 |
function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
|
||
| 13637 |
bytes32 m0; |
||
| 13638 |
bytes32 m1; |
||
| 13639 |
bytes32 m2; |
||
| 13640 |
bytes32 m3; |
||
| 13641 |
bytes32 m4; |
||
| 13642 |
bytes32 m5; |
||
| 13643 |
bytes32 m6; |
||
| 13644 |
bytes32 m7; |
||
| 13645 |
bytes32 m8; |
||
| 13646 |
bytes32 m9; |
||
| 13647 |
bytes32 m10; |
||
| 13648 |
/// @solidity memory-safe-assembly |
||
| 13649 |
assembly {
|
||
| 13650 |
function writeString(pos, w) {
|
||
| 13651 |
let length := 0 |
||
| 13652 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13653 |
mstore(pos, length) |
||
| 13654 |
let shift := sub(256, shl(3, length)) |
||
| 13655 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13656 |
} |
||
| 13657 |
m0 := mload(0x00) |
||
| 13658 |
m1 := mload(0x20) |
||
| 13659 |
m2 := mload(0x40) |
||
| 13660 |
m3 := mload(0x60) |
||
| 13661 |
m4 := mload(0x80) |
||
| 13662 |
m5 := mload(0xa0) |
||
| 13663 |
m6 := mload(0xc0) |
||
| 13664 |
m7 := mload(0xe0) |
||
| 13665 |
m8 := mload(0x100) |
||
| 13666 |
m9 := mload(0x120) |
||
| 13667 |
m10 := mload(0x140) |
||
| 13668 |
// Selector of `log(string,string,uint256,string)`. |
||
| 13669 |
mstore(0x00, 0x5d1a971a) |
||
| 13670 |
mstore(0x20, 0x80) |
||
| 13671 |
mstore(0x40, 0xc0) |
||
| 13672 |
mstore(0x60, p2) |
||
| 13673 |
mstore(0x80, 0x100) |
||
| 13674 |
writeString(0xa0, p0) |
||
| 13675 |
writeString(0xe0, p1) |
||
| 13676 |
writeString(0x120, p3) |
||
| 13677 |
} |
||
| 13678 |
_sendLogPayload(0x1c, 0x144); |
||
| 13679 |
/// @solidity memory-safe-assembly |
||
| 13680 |
assembly {
|
||
| 13681 |
mstore(0x00, m0) |
||
| 13682 |
mstore(0x20, m1) |
||
| 13683 |
mstore(0x40, m2) |
||
| 13684 |
mstore(0x60, m3) |
||
| 13685 |
mstore(0x80, m4) |
||
| 13686 |
mstore(0xa0, m5) |
||
| 13687 |
mstore(0xc0, m6) |
||
| 13688 |
mstore(0xe0, m7) |
||
| 13689 |
mstore(0x100, m8) |
||
| 13690 |
mstore(0x120, m9) |
||
| 13691 |
mstore(0x140, m10) |
||
| 13692 |
} |
||
| 13693 |
} |
||
| 13694 | |||
| 13695 |
function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
|
||
| 13696 |
bytes32 m0; |
||
| 13697 |
bytes32 m1; |
||
| 13698 |
bytes32 m2; |
||
| 13699 |
bytes32 m3; |
||
| 13700 |
bytes32 m4; |
||
| 13701 |
bytes32 m5; |
||
| 13702 |
bytes32 m6; |
||
| 13703 |
bytes32 m7; |
||
| 13704 |
bytes32 m8; |
||
| 13705 |
bytes32 m9; |
||
| 13706 |
bytes32 m10; |
||
| 13707 |
/// @solidity memory-safe-assembly |
||
| 13708 |
assembly {
|
||
| 13709 |
function writeString(pos, w) {
|
||
| 13710 |
let length := 0 |
||
| 13711 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13712 |
mstore(pos, length) |
||
| 13713 |
let shift := sub(256, shl(3, length)) |
||
| 13714 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13715 |
} |
||
| 13716 |
m0 := mload(0x00) |
||
| 13717 |
m1 := mload(0x20) |
||
| 13718 |
m2 := mload(0x40) |
||
| 13719 |
m3 := mload(0x60) |
||
| 13720 |
m4 := mload(0x80) |
||
| 13721 |
m5 := mload(0xa0) |
||
| 13722 |
m6 := mload(0xc0) |
||
| 13723 |
m7 := mload(0xe0) |
||
| 13724 |
m8 := mload(0x100) |
||
| 13725 |
m9 := mload(0x120) |
||
| 13726 |
m10 := mload(0x140) |
||
| 13727 |
// Selector of `log(string,string,string,address)`. |
||
| 13728 |
mstore(0x00, 0x6d572f44) |
||
| 13729 |
mstore(0x20, 0x80) |
||
| 13730 |
mstore(0x40, 0xc0) |
||
| 13731 |
mstore(0x60, 0x100) |
||
| 13732 |
mstore(0x80, p3) |
||
| 13733 |
writeString(0xa0, p0) |
||
| 13734 |
writeString(0xe0, p1) |
||
| 13735 |
writeString(0x120, p2) |
||
| 13736 |
} |
||
| 13737 |
_sendLogPayload(0x1c, 0x144); |
||
| 13738 |
/// @solidity memory-safe-assembly |
||
| 13739 |
assembly {
|
||
| 13740 |
mstore(0x00, m0) |
||
| 13741 |
mstore(0x20, m1) |
||
| 13742 |
mstore(0x40, m2) |
||
| 13743 |
mstore(0x60, m3) |
||
| 13744 |
mstore(0x80, m4) |
||
| 13745 |
mstore(0xa0, m5) |
||
| 13746 |
mstore(0xc0, m6) |
||
| 13747 |
mstore(0xe0, m7) |
||
| 13748 |
mstore(0x100, m8) |
||
| 13749 |
mstore(0x120, m9) |
||
| 13750 |
mstore(0x140, m10) |
||
| 13751 |
} |
||
| 13752 |
} |
||
| 13753 | |||
| 13754 |
function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
|
||
| 13755 |
bytes32 m0; |
||
| 13756 |
bytes32 m1; |
||
| 13757 |
bytes32 m2; |
||
| 13758 |
bytes32 m3; |
||
| 13759 |
bytes32 m4; |
||
| 13760 |
bytes32 m5; |
||
| 13761 |
bytes32 m6; |
||
| 13762 |
bytes32 m7; |
||
| 13763 |
bytes32 m8; |
||
| 13764 |
bytes32 m9; |
||
| 13765 |
bytes32 m10; |
||
| 13766 |
/// @solidity memory-safe-assembly |
||
| 13767 |
assembly {
|
||
| 13768 |
function writeString(pos, w) {
|
||
| 13769 |
let length := 0 |
||
| 13770 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13771 |
mstore(pos, length) |
||
| 13772 |
let shift := sub(256, shl(3, length)) |
||
| 13773 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13774 |
} |
||
| 13775 |
m0 := mload(0x00) |
||
| 13776 |
m1 := mload(0x20) |
||
| 13777 |
m2 := mload(0x40) |
||
| 13778 |
m3 := mload(0x60) |
||
| 13779 |
m4 := mload(0x80) |
||
| 13780 |
m5 := mload(0xa0) |
||
| 13781 |
m6 := mload(0xc0) |
||
| 13782 |
m7 := mload(0xe0) |
||
| 13783 |
m8 := mload(0x100) |
||
| 13784 |
m9 := mload(0x120) |
||
| 13785 |
m10 := mload(0x140) |
||
| 13786 |
// Selector of `log(string,string,string,bool)`. |
||
| 13787 |
mstore(0x00, 0x2c1754ed) |
||
| 13788 |
mstore(0x20, 0x80) |
||
| 13789 |
mstore(0x40, 0xc0) |
||
| 13790 |
mstore(0x60, 0x100) |
||
| 13791 |
mstore(0x80, p3) |
||
| 13792 |
writeString(0xa0, p0) |
||
| 13793 |
writeString(0xe0, p1) |
||
| 13794 |
writeString(0x120, p2) |
||
| 13795 |
} |
||
| 13796 |
_sendLogPayload(0x1c, 0x144); |
||
| 13797 |
/// @solidity memory-safe-assembly |
||
| 13798 |
assembly {
|
||
| 13799 |
mstore(0x00, m0) |
||
| 13800 |
mstore(0x20, m1) |
||
| 13801 |
mstore(0x40, m2) |
||
| 13802 |
mstore(0x60, m3) |
||
| 13803 |
mstore(0x80, m4) |
||
| 13804 |
mstore(0xa0, m5) |
||
| 13805 |
mstore(0xc0, m6) |
||
| 13806 |
mstore(0xe0, m7) |
||
| 13807 |
mstore(0x100, m8) |
||
| 13808 |
mstore(0x120, m9) |
||
| 13809 |
mstore(0x140, m10) |
||
| 13810 |
} |
||
| 13811 |
} |
||
| 13812 | |||
| 13813 |
function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
|
||
| 13814 |
bytes32 m0; |
||
| 13815 |
bytes32 m1; |
||
| 13816 |
bytes32 m2; |
||
| 13817 |
bytes32 m3; |
||
| 13818 |
bytes32 m4; |
||
| 13819 |
bytes32 m5; |
||
| 13820 |
bytes32 m6; |
||
| 13821 |
bytes32 m7; |
||
| 13822 |
bytes32 m8; |
||
| 13823 |
bytes32 m9; |
||
| 13824 |
bytes32 m10; |
||
| 13825 |
/// @solidity memory-safe-assembly |
||
| 13826 |
assembly {
|
||
| 13827 |
function writeString(pos, w) {
|
||
| 13828 |
let length := 0 |
||
| 13829 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13830 |
mstore(pos, length) |
||
| 13831 |
let shift := sub(256, shl(3, length)) |
||
| 13832 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13833 |
} |
||
| 13834 |
m0 := mload(0x00) |
||
| 13835 |
m1 := mload(0x20) |
||
| 13836 |
m2 := mload(0x40) |
||
| 13837 |
m3 := mload(0x60) |
||
| 13838 |
m4 := mload(0x80) |
||
| 13839 |
m5 := mload(0xa0) |
||
| 13840 |
m6 := mload(0xc0) |
||
| 13841 |
m7 := mload(0xe0) |
||
| 13842 |
m8 := mload(0x100) |
||
| 13843 |
m9 := mload(0x120) |
||
| 13844 |
m10 := mload(0x140) |
||
| 13845 |
// Selector of `log(string,string,string,uint256)`. |
||
| 13846 |
mstore(0x00, 0x8eafb02b) |
||
| 13847 |
mstore(0x20, 0x80) |
||
| 13848 |
mstore(0x40, 0xc0) |
||
| 13849 |
mstore(0x60, 0x100) |
||
| 13850 |
mstore(0x80, p3) |
||
| 13851 |
writeString(0xa0, p0) |
||
| 13852 |
writeString(0xe0, p1) |
||
| 13853 |
writeString(0x120, p2) |
||
| 13854 |
} |
||
| 13855 |
_sendLogPayload(0x1c, 0x144); |
||
| 13856 |
/// @solidity memory-safe-assembly |
||
| 13857 |
assembly {
|
||
| 13858 |
mstore(0x00, m0) |
||
| 13859 |
mstore(0x20, m1) |
||
| 13860 |
mstore(0x40, m2) |
||
| 13861 |
mstore(0x60, m3) |
||
| 13862 |
mstore(0x80, m4) |
||
| 13863 |
mstore(0xa0, m5) |
||
| 13864 |
mstore(0xc0, m6) |
||
| 13865 |
mstore(0xe0, m7) |
||
| 13866 |
mstore(0x100, m8) |
||
| 13867 |
mstore(0x120, m9) |
||
| 13868 |
mstore(0x140, m10) |
||
| 13869 |
} |
||
| 13870 |
} |
||
| 13871 | |||
| 13872 |
function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
|
||
| 13873 |
bytes32 m0; |
||
| 13874 |
bytes32 m1; |
||
| 13875 |
bytes32 m2; |
||
| 13876 |
bytes32 m3; |
||
| 13877 |
bytes32 m4; |
||
| 13878 |
bytes32 m5; |
||
| 13879 |
bytes32 m6; |
||
| 13880 |
bytes32 m7; |
||
| 13881 |
bytes32 m8; |
||
| 13882 |
bytes32 m9; |
||
| 13883 |
bytes32 m10; |
||
| 13884 |
bytes32 m11; |
||
| 13885 |
bytes32 m12; |
||
| 13886 |
/// @solidity memory-safe-assembly |
||
| 13887 |
assembly {
|
||
| 13888 |
function writeString(pos, w) {
|
||
| 13889 |
let length := 0 |
||
| 13890 |
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
|
||
| 13891 |
mstore(pos, length) |
||
| 13892 |
let shift := sub(256, shl(3, length)) |
||
| 13893 |
mstore(add(pos, 0x20), shl(shift, shr(shift, w))) |
||
| 13894 |
} |
||
| 13895 |
m0 := mload(0x00) |
||
| 13896 |
m1 := mload(0x20) |
||
| 13897 |
m2 := mload(0x40) |
||
| 13898 |
m3 := mload(0x60) |
||
| 13899 |
m4 := mload(0x80) |
||
| 13900 |
m5 := mload(0xa0) |
||
| 13901 |
m6 := mload(0xc0) |
||
| 13902 |
m7 := mload(0xe0) |
||
| 13903 |
m8 := mload(0x100) |
||
| 13904 |
m9 := mload(0x120) |
||
| 13905 |
m10 := mload(0x140) |
||
| 13906 |
m11 := mload(0x160) |
||
| 13907 |
m12 := mload(0x180) |
||
| 13908 |
// Selector of `log(string,string,string,string)`. |
||
| 13909 |
mstore(0x00, 0xde68f20a) |
||
| 13910 |
mstore(0x20, 0x80) |
||
| 13911 |
mstore(0x40, 0xc0) |
||
| 13912 |
mstore(0x60, 0x100) |
||
| 13913 |
mstore(0x80, 0x140) |
||
| 13914 |
writeString(0xa0, p0) |
||
| 13915 |
writeString(0xe0, p1) |
||
| 13916 |
writeString(0x120, p2) |
||
| 13917 |
writeString(0x160, p3) |
||
| 13918 |
} |
||
| 13919 |
_sendLogPayload(0x1c, 0x184); |
||
| 13920 |
/// @solidity memory-safe-assembly |
||
| 13921 |
assembly {
|
||
| 13922 |
mstore(0x00, m0) |
||
| 13923 |
mstore(0x20, m1) |
||
| 13924 |
mstore(0x40, m2) |
||
| 13925 |
mstore(0x60, m3) |
||
| 13926 |
mstore(0x80, m4) |
||
| 13927 |
mstore(0xa0, m5) |
||
| 13928 |
mstore(0xc0, m6) |
||
| 13929 |
mstore(0xe0, m7) |
||
| 13930 |
mstore(0x100, m8) |
||
| 13931 |
mstore(0x120, m9) |
||
| 13932 |
mstore(0x140, m10) |
||
| 13933 |
mstore(0x160, m11) |
||
| 13934 |
mstore(0x180, m12) |
||
| 13935 |
} |
||
| 13936 |
} |
||
| 13937 |
} |
||
| 13938 |
| Lines covered: | 0 / 8 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol) |
||
| 3 | |||
| 4 |
pragma solidity ^0.8.20; |
||
| 5 | |||
| 6 |
/** |
||
| 7 |
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM |
||
| 8 |
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to |
||
| 9 |
* be specified by overriding the virtual {_implementation} function.
|
||
| 10 |
* |
||
| 11 |
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
|
||
| 12 |
* different contract through the {_delegate} function.
|
||
| 13 |
* |
||
| 14 |
* The success and return data of the delegated call will be returned back to the caller of the proxy. |
||
| 15 |
*/ |
||
| 16 |
abstract contract Proxy {
|
||
| 17 |
/** |
||
| 18 |
* @dev Delegates the current call to `implementation`. |
||
| 19 |
* |
||
| 20 |
* This function does not return to its internal call site, it will return directly to the external caller. |
||
| 21 |
*/ |
||
| 22 |
function _delegate(address implementation) internal virtual {
|
||
| 23 |
assembly {
|
||
| 24 |
// Copy msg.data. We take full control of memory in this inline assembly |
||
| 25 |
// block because it will not return to Solidity code. We overwrite the |
||
| 26 |
// Solidity scratch pad at memory position 0. |
||
| 27 |
calldatacopy(0, 0, calldatasize()) |
||
| 28 | |||
| 29 |
// Call the implementation. |
||
| 30 |
// out and outsize are 0 because we don't know the size yet. |
||
| 31 |
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) |
||
| 32 | |||
| 33 |
// Copy the returned data. |
||
| 34 |
returndatacopy(0, 0, returndatasize()) |
||
| 35 | |||
| 36 |
switch result |
||
| 37 |
// delegatecall returns 0 on error. |
||
| 38 |
case 0 {
|
||
| 39 |
revert(0, returndatasize()) |
||
| 40 |
} |
||
| 41 |
default {
|
||
| 42 |
return(0, returndatasize()) |
||
| 43 |
} |
||
| 44 |
} |
||
| 45 |
} |
||
| 46 | |||
| 47 |
/** |
||
| 48 |
* @dev This is a virtual function that should be overridden so it returns the address to which the fallback |
||
| 49 |
* function and {_fallback} should delegate.
|
||
| 50 |
*/ |
||
| 51 |
function _implementation() internal view virtual returns (address); |
||
| 52 | |||
| 53 |
/** |
||
| 54 |
* @dev Delegates the current call to the address returned by `_implementation()`. |
||
| 55 |
* |
||
| 56 |
* This function does not return to its internal call site, it will return directly to the external caller. |
||
| 57 |
*/ |
||
| 58 |
function _fallback() internal virtual {
|
||
| 59 |
_delegate(_implementation()); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
/** |
||
| 63 |
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other |
||
| 64 |
* function in the contract matches the call data. |
||
| 65 |
*/ |
||
| 66 |
fallback() external payable virtual {
|
||
| 67 |
_fallback(); |
||
| 68 |
} |
||
| 69 |
} |
||
| 70 |
| Lines covered: | 4 / 6 (66.7%) |
|---|
| 1 |
// SPDX-License-Identifier: AGPL-3.0-only |
||
| 2 |
pragma solidity >=0.8.0; |
||
| 3 | |||
| 4 |
/// @notice Simple single owner authorization mixin. |
||
| 5 |
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) |
||
| 6 |
abstract contract Owned {
|
||
| 7 |
/*////////////////////////////////////////////////////////////// |
||
| 8 |
EVENTS |
||
| 9 |
//////////////////////////////////////////////////////////////*/ |
||
| 10 | |||
| 11 |
event OwnershipTransferred(address indexed user, address indexed newOwner); |
||
| 12 | |||
| 13 |
/*////////////////////////////////////////////////////////////// |
||
| 14 |
OWNERSHIP STORAGE |
||
| 15 |
//////////////////////////////////////////////////////////////*/ |
||
| 16 | |||
| 17 |
√ 4
|
⟳ 4
|
address public owner; |
| 18 | |||
| 19 |
modifier onlyOwner() virtual {
|
||
| 20 |
√ 5
|
⟳ 5
|
require(msg.sender == owner, "UNAUTHORIZED"); |
| 21 | |||
| 22 |
_; |
||
| 23 |
} |
||
| 24 | |||
| 25 |
/*////////////////////////////////////////////////////////////// |
||
| 26 |
CONSTRUCTOR |
||
| 27 |
//////////////////////////////////////////////////////////////*/ |
||
| 28 | |||
| 29 |
constructor(address _owner) {
|
||
| 30 |
√ 3
|
owner = _owner; |
|
| 31 | |||
| 32 |
√ 5
|
emit OwnershipTransferred(address(0), _owner); |
|
| 33 |
} |
||
| 34 | |||
| 35 |
/*////////////////////////////////////////////////////////////// |
||
| 36 |
OWNERSHIP LOGIC |
||
| 37 |
//////////////////////////////////////////////////////////////*/ |
||
| 38 | |||
| 39 |
function transferOwnership(address newOwner) public virtual onlyOwner {
|
||
| 40 |
owner = newOwner; |
||
| 41 | |||
| 42 |
emit OwnershipTransferred(msg.sender, newOwner); |
||
| 43 |
} |
||
| 44 |
} |
||
| 45 |
| Lines covered: | 2 / 3 (66.7%) |
|---|
| 1 |
// SPDX-License-Identifier: AGPL-3.0-only |
||
| 2 |
pragma solidity >=0.8.0; |
||
| 3 | |||
| 4 |
import {ERC20} from "../../../tokens/ERC20.sol";
|
||
| 5 | |||
| 6 |
contract MockERC20 is ERC20 {
|
||
| 7 |
constructor( |
||
| 8 |
string memory _name, |
||
| 9 |
string memory _symbol, |
||
| 10 |
uint8 _decimals |
||
| 11 |
√ 4
|
) ERC20(_name, _symbol, _decimals) {}
|
|
| 12 | |||
| 13 |
function mint(address to, uint256 value) public virtual {
|
||
| 14 |
√ 3
|
_mint(to, value); |
|
| 15 |
} |
||
| 16 | |||
| 17 |
function burn(address from, uint256 value) public virtual {
|
||
| 18 |
_burn(from, value); |
||
| 19 |
} |
||
| 20 |
} |
||
| 21 |
| Lines covered: | 32 / 49 (65.3%) |
|---|
| 1 |
// SPDX-License-Identifier: AGPL-3.0-only |
||
| 2 |
pragma solidity >=0.8.0; |
||
| 3 | |||
| 4 |
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. |
||
| 5 |
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) |
||
| 6 |
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) |
||
| 7 |
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. |
||
| 8 |
abstract contract ERC20 {
|
||
| 9 |
/*////////////////////////////////////////////////////////////// |
||
| 10 |
EVENTS |
||
| 11 |
//////////////////////////////////////////////////////////////*/ |
||
| 12 | |||
| 13 |
event Transfer(address indexed from, address indexed to, uint256 amount); |
||
| 14 | |||
| 15 |
event Approval(address indexed owner, address indexed spender, uint256 amount); |
||
| 16 | |||
| 17 |
/*////////////////////////////////////////////////////////////// |
||
| 18 |
METADATA STORAGE |
||
| 19 |
//////////////////////////////////////////////////////////////*/ |
||
| 20 | |||
| 21 |
√ 8
|
⟳ 8
|
string public name; |
| 22 | |||
| 23 |
string public symbol; |
||
| 24 | |||
| 25 |
uint8 public immutable decimals; |
||
| 26 | |||
| 27 |
/*////////////////////////////////////////////////////////////// |
||
| 28 |
ERC20 STORAGE |
||
| 29 |
//////////////////////////////////////////////////////////////*/ |
||
| 30 | |||
| 31 |
√ 4
|
⟳ 4
|
uint256 public totalSupply; |
| 32 | |||
| 33 |
√ 21
|
⟳ 21
|
mapping(address => uint256) public balanceOf; |
| 34 | |||
| 35 |
mapping(address => mapping(address => uint256)) public allowance; |
||
| 36 | |||
| 37 |
/*////////////////////////////////////////////////////////////// |
||
| 38 |
EIP-2612 STORAGE |
||
| 39 |
//////////////////////////////////////////////////////////////*/ |
||
| 40 | |||
| 41 |
uint256 internal immutable INITIAL_CHAIN_ID; |
||
| 42 | |||
| 43 |
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; |
||
| 44 | |||
| 45 |
mapping(address => uint256) public nonces; |
||
| 46 | |||
| 47 |
/*////////////////////////////////////////////////////////////// |
||
| 48 |
CONSTRUCTOR |
||
| 49 |
//////////////////////////////////////////////////////////////*/ |
||
| 50 | |||
| 51 |
constructor( |
||
| 52 |
string memory _name, |
||
| 53 |
string memory _symbol, |
||
| 54 |
uint8 _decimals |
||
| 55 |
) {
|
||
| 56 |
√ 2
|
name = _name; |
|
| 57 |
√ 3
|
symbol = _symbol; |
|
| 58 |
√ 5
|
decimals = _decimals; |
|
| 59 | |||
| 60 |
√ 1
|
INITIAL_CHAIN_ID = block.chainid; |
|
| 61 |
√ 1
|
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); |
|
| 62 |
} |
||
| 63 | |||
| 64 |
/*////////////////////////////////////////////////////////////// |
||
| 65 |
ERC20 LOGIC |
||
| 66 |
//////////////////////////////////////////////////////////////*/ |
||
| 67 | |||
| 68 |
√ 3
|
function approve(address spender, uint256 amount) public virtual returns (bool) {
|
|
| 69 |
√ 3
|
allowance[msg.sender][spender] = amount; |
|
| 70 | |||
| 71 |
√ 13
|
⟳ 8
|
emit Approval(msg.sender, spender, amount); |
| 72 | |||
| 73 |
√ 1
|
⟳ 1
|
return true; |
| 74 |
} |
||
| 75 | |||
| 76 |
√ 3
|
⟳ 3
|
function transfer(address to, uint256 amount) public virtual returns (bool) {
|
| 77 |
√ 6
|
⟳ 6
|
balanceOf[msg.sender] -= amount; |
| 78 | |||
| 79 |
// Cannot overflow because the sum of all user |
||
| 80 |
// balances can't exceed the max uint256 value. |
||
| 81 |
unchecked {
|
||
| 82 |
√ 2
|
⟳ 2
|
balanceOf[to] += amount; |
| 83 |
} |
||
| 84 | |||
| 85 |
√ 2
|
⟳ 2
|
emit Transfer(msg.sender, to, amount); |
| 86 | |||
| 87 |
return true; |
||
| 88 |
} |
||
| 89 | |||
| 90 |
function transferFrom( |
||
| 91 |
address from, |
||
| 92 |
address to, |
||
| 93 |
uint256 amount |
||
| 94 |
√ 1
|
⟳ 1
|
) public virtual returns (bool) {
|
| 95 |
√ 2
|
⟳ 2
|
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. |
| 96 | |||
| 97 |
√ 5
|
⟳ 5
|
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; |
| 98 | |||
| 99 |
√ 5
|
⟳ 5
|
balanceOf[from] -= amount; |
| 100 | |||
| 101 |
// Cannot overflow because the sum of all user |
||
| 102 |
// balances can't exceed the max uint256 value. |
||
| 103 |
unchecked {
|
||
| 104 |
√ 2
|
⟳ 2
|
balanceOf[to] += amount; |
| 105 |
} |
||
| 106 | |||
| 107 |
√ 16
|
⟳ 16
|
emit Transfer(from, to, amount); |
| 108 | |||
| 109 |
√ 2
|
⟳ 2
|
return true; |
| 110 |
} |
||
| 111 | |||
| 112 |
/*////////////////////////////////////////////////////////////// |
||
| 113 |
EIP-2612 LOGIC |
||
| 114 |
//////////////////////////////////////////////////////////////*/ |
||
| 115 | |||
| 116 |
function permit( |
||
| 117 |
address owner, |
||
| 118 |
address spender, |
||
| 119 |
uint256 value, |
||
| 120 |
uint256 deadline, |
||
| 121 |
uint8 v, |
||
| 122 |
bytes32 r, |
||
| 123 |
bytes32 s |
||
| 124 |
) public virtual {
|
||
| 125 |
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); |
||
| 126 | |||
| 127 |
// Unchecked because the only math done is incrementing |
||
| 128 |
// the owner's nonce which cannot realistically overflow. |
||
| 129 |
unchecked {
|
||
| 130 |
address recoveredAddress = ecrecover( |
||
| 131 |
keccak256( |
||
| 132 |
abi.encodePacked( |
||
| 133 |
"\x19\x01", |
||
| 134 |
DOMAIN_SEPARATOR(), |
||
| 135 |
keccak256( |
||
| 136 |
abi.encode( |
||
| 137 |
keccak256( |
||
| 138 |
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" |
||
| 139 |
), |
||
| 140 |
owner, |
||
| 141 |
spender, |
||
| 142 |
value, |
||
| 143 |
nonces[owner]++, |
||
| 144 |
deadline |
||
| 145 |
) |
||
| 146 |
) |
||
| 147 |
) |
||
| 148 |
), |
||
| 149 |
v, |
||
| 150 |
r, |
||
| 151 |
s |
||
| 152 |
); |
||
| 153 | |||
| 154 |
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); |
||
| 155 | |||
| 156 |
allowance[recoveredAddress][spender] = value; |
||
| 157 |
} |
||
| 158 | |||
| 159 |
emit Approval(owner, spender, value); |
||
| 160 |
} |
||
| 161 | |||
| 162 |
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
|
||
| 163 |
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); |
||
| 164 |
} |
||
| 165 | |||
| 166 |
√ 1
|
function computeDomainSeparator() internal view virtual returns (bytes32) {
|
|
| 167 |
return |
||
| 168 |
keccak256( |
||
| 169 |
abi.encode( |
||
| 170 |
√ 1
|
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
|
|
| 171 |
√ 1
|
keccak256(bytes(name)), |
|
| 172 |
√ 1
|
keccak256("1"),
|
|
| 173 |
√ 1
|
block.chainid, |
|
| 174 |
√ 1
|
address(this) |
|
| 175 |
) |
||
| 176 |
); |
||
| 177 |
} |
||
| 178 | |||
| 179 |
/*////////////////////////////////////////////////////////////// |
||
| 180 |
INTERNAL MINT/BURN LOGIC |
||
| 181 |
//////////////////////////////////////////////////////////////*/ |
||
| 182 | |||
| 183 |
function _mint(address to, uint256 amount) internal virtual {
|
||
| 184 |
√ 3
|
totalSupply += amount; |
|
| 185 | |||
| 186 |
// Cannot overflow because the sum of all user |
||
| 187 |
// balances can't exceed the max uint256 value. |
||
| 188 |
unchecked {
|
||
| 189 |
√ 1
|
balanceOf[to] += amount; |
|
| 190 |
} |
||
| 191 | |||
| 192 |
√ 11
|
emit Transfer(address(0), to, amount); |
|
| 193 |
} |
||
| 194 | |||
| 195 |
function _burn(address from, uint256 amount) internal virtual {
|
||
| 196 |
balanceOf[from] -= amount; |
||
| 197 | |||
| 198 |
// Cannot underflow because a user's balance |
||
| 199 |
// will never be larger than the total supply. |
||
| 200 |
unchecked {
|
||
| 201 |
totalSupply -= amount; |
||
| 202 |
} |
||
| 203 | |||
| 204 |
emit Transfer(from, address(0), amount); |
||
| 205 |
} |
||
| 206 |
} |
||
| 207 |
| Lines covered: | 0 / 8 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: AGPL-3.0-only |
||
| 2 |
pragma solidity >=0.8.0; |
||
| 3 | |||
| 4 |
/// @notice Arithmetic library with operations for fixed-point numbers. |
||
| 5 |
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) |
||
| 6 |
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) |
||
| 7 |
library FixedPointMathLib {
|
||
| 8 |
/*////////////////////////////////////////////////////////////// |
||
| 9 |
SIMPLIFIED FIXED POINT OPERATIONS |
||
| 10 |
//////////////////////////////////////////////////////////////*/ |
||
| 11 | |||
| 12 |
uint256 internal constant MAX_UINT256 = 2**256 - 1; |
||
| 13 | |||
| 14 |
uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. |
||
| 15 | |||
| 16 |
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
|
||
| 17 |
return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. |
||
| 18 |
} |
||
| 19 | |||
| 20 |
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
|
||
| 21 |
return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
|
||
| 25 |
return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
|
||
| 29 |
return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. |
||
| 30 |
} |
||
| 31 | |||
| 32 |
/*////////////////////////////////////////////////////////////// |
||
| 33 |
LOW LEVEL FIXED POINT OPERATIONS |
||
| 34 |
//////////////////////////////////////////////////////////////*/ |
||
| 35 | |||
| 36 |
function mulDivDown( |
||
| 37 |
uint256 x, |
||
| 38 |
uint256 y, |
||
| 39 |
uint256 denominator |
||
| 40 |
) internal pure returns (uint256 z) {
|
||
| 41 |
/// @solidity memory-safe-assembly |
||
| 42 |
assembly {
|
||
| 43 |
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) |
||
| 44 |
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
|
||
| 45 |
revert(0, 0) |
||
| 46 |
} |
||
| 47 | |||
| 48 |
// Divide x * y by the denominator. |
||
| 49 |
z := div(mul(x, y), denominator) |
||
| 50 |
} |
||
| 51 |
} |
||
| 52 | |||
| 53 |
function mulDivUp( |
||
| 54 |
uint256 x, |
||
| 55 |
uint256 y, |
||
| 56 |
uint256 denominator |
||
| 57 |
) internal pure returns (uint256 z) {
|
||
| 58 |
/// @solidity memory-safe-assembly |
||
| 59 |
assembly {
|
||
| 60 |
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) |
||
| 61 |
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
|
||
| 62 |
revert(0, 0) |
||
| 63 |
} |
||
| 64 | |||
| 65 |
// If x * y modulo the denominator is strictly greater than 0, |
||
| 66 |
// 1 is added to round up the division of x * y by the denominator. |
||
| 67 |
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) |
||
| 68 |
} |
||
| 69 |
} |
||
| 70 | |||
| 71 |
function rpow( |
||
| 72 |
uint256 x, |
||
| 73 |
uint256 n, |
||
| 74 |
uint256 scalar |
||
| 75 |
) internal pure returns (uint256 z) {
|
||
| 76 |
/// @solidity memory-safe-assembly |
||
| 77 |
assembly {
|
||
| 78 |
switch x |
||
| 79 |
case 0 {
|
||
| 80 |
switch n |
||
| 81 |
case 0 {
|
||
| 82 |
// 0 ** 0 = 1 |
||
| 83 |
z := scalar |
||
| 84 |
} |
||
| 85 |
default {
|
||
| 86 |
// 0 ** n = 0 |
||
| 87 |
z := 0 |
||
| 88 |
} |
||
| 89 |
} |
||
| 90 |
default {
|
||
| 91 |
switch mod(n, 2) |
||
| 92 |
case 0 {
|
||
| 93 |
// If n is even, store scalar in z for now. |
||
| 94 |
z := scalar |
||
| 95 |
} |
||
| 96 |
default {
|
||
| 97 |
// If n is odd, store x in z for now. |
||
| 98 |
z := x |
||
| 99 |
} |
||
| 100 | |||
| 101 |
// Shifting right by 1 is like dividing by 2. |
||
| 102 |
let half := shr(1, scalar) |
||
| 103 | |||
| 104 |
for {
|
||
| 105 |
// Shift n right by 1 before looping to halve it. |
||
| 106 |
n := shr(1, n) |
||
| 107 |
} n {
|
||
| 108 |
// Shift n right by 1 each iteration to halve it. |
||
| 109 |
n := shr(1, n) |
||
| 110 |
} {
|
||
| 111 |
// Revert immediately if x ** 2 would overflow. |
||
| 112 |
// Equivalent to iszero(eq(div(xx, x), x)) here. |
||
| 113 |
if shr(128, x) {
|
||
| 114 |
revert(0, 0) |
||
| 115 |
} |
||
| 116 | |||
| 117 |
// Store x squared. |
||
| 118 |
let xx := mul(x, x) |
||
| 119 | |||
| 120 |
// Round to the nearest number. |
||
| 121 |
let xxRound := add(xx, half) |
||
| 122 | |||
| 123 |
// Revert if xx + half overflowed. |
||
| 124 |
if lt(xxRound, xx) {
|
||
| 125 |
revert(0, 0) |
||
| 126 |
} |
||
| 127 | |||
| 128 |
// Set x to scaled xxRound. |
||
| 129 |
x := div(xxRound, scalar) |
||
| 130 | |||
| 131 |
// If n is even: |
||
| 132 |
if mod(n, 2) {
|
||
| 133 |
// Compute z * x. |
||
| 134 |
let zx := mul(z, x) |
||
| 135 | |||
| 136 |
// If z * x overflowed: |
||
| 137 |
if iszero(eq(div(zx, x), z)) {
|
||
| 138 |
// Revert if x is non-zero. |
||
| 139 |
if iszero(iszero(x)) {
|
||
| 140 |
revert(0, 0) |
||
| 141 |
} |
||
| 142 |
} |
||
| 143 | |||
| 144 |
// Round to the nearest number. |
||
| 145 |
let zxRound := add(zx, half) |
||
| 146 | |||
| 147 |
// Revert if zx + half overflowed. |
||
| 148 |
if lt(zxRound, zx) {
|
||
| 149 |
revert(0, 0) |
||
| 150 |
} |
||
| 151 | |||
| 152 |
// Return properly scaled zxRound. |
||
| 153 |
z := div(zxRound, scalar) |
||
| 154 |
} |
||
| 155 |
} |
||
| 156 |
} |
||
| 157 |
} |
||
| 158 |
} |
||
| 159 | |||
| 160 |
/*////////////////////////////////////////////////////////////// |
||
| 161 |
GENERAL NUMBER UTILITIES |
||
| 162 |
//////////////////////////////////////////////////////////////*/ |
||
| 163 | |||
| 164 |
function sqrt(uint256 x) internal pure returns (uint256 z) {
|
||
| 165 |
/// @solidity memory-safe-assembly |
||
| 166 |
assembly {
|
||
| 167 |
let y := x // We start y at x, which will help us make our initial estimate. |
||
| 168 | |||
| 169 |
z := 181 // The "correct" value is 1, but this saves a multiplication later. |
||
| 170 | |||
| 171 |
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad |
||
| 172 |
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. |
||
| 173 | |||
| 174 |
// We check y >= 2^(k + 8) but shift right by k bits |
||
| 175 |
// each branch to ensure that if x >= 256, then y >= 256. |
||
| 176 |
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
|
||
| 177 |
y := shr(128, y) |
||
| 178 |
z := shl(64, z) |
||
| 179 |
} |
||
| 180 |
if iszero(lt(y, 0x1000000000000000000)) {
|
||
| 181 |
y := shr(64, y) |
||
| 182 |
z := shl(32, z) |
||
| 183 |
} |
||
| 184 |
if iszero(lt(y, 0x10000000000)) {
|
||
| 185 |
y := shr(32, y) |
||
| 186 |
z := shl(16, z) |
||
| 187 |
} |
||
| 188 |
if iszero(lt(y, 0x1000000)) {
|
||
| 189 |
y := shr(16, y) |
||
| 190 |
z := shl(8, z) |
||
| 191 |
} |
||
| 192 | |||
| 193 |
// Goal was to get z*z*y within a small factor of x. More iterations could |
||
| 194 |
// get y in a tighter range. Currently, we will have y in [256, 256*2^16). |
||
| 195 |
// We ensured y >= 256 so that the relative difference between y and y+1 is small. |
||
| 196 |
// That's not possible if x < 256 but we can just verify those cases exhaustively. |
||
| 197 | |||
| 198 |
// Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. |
||
| 199 |
// Correctness can be checked exhaustively for x < 256, so we assume y >= 256. |
||
| 200 |
// Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. |
||
| 201 | |||
| 202 |
// For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range |
||
| 203 |
// (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. |
||
| 204 | |||
| 205 |
// Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate |
||
| 206 |
// sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. |
||
| 207 | |||
| 208 |
// There is no overflow risk here since y < 2^136 after the first branch above. |
||
| 209 |
z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. |
||
| 210 | |||
| 211 |
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. |
||
| 212 |
z := shr(1, add(z, div(x, z))) |
||
| 213 |
z := shr(1, add(z, div(x, z))) |
||
| 214 |
z := shr(1, add(z, div(x, z))) |
||
| 215 |
z := shr(1, add(z, div(x, z))) |
||
| 216 |
z := shr(1, add(z, div(x, z))) |
||
| 217 |
z := shr(1, add(z, div(x, z))) |
||
| 218 |
z := shr(1, add(z, div(x, z))) |
||
| 219 | |||
| 220 |
// If x+1 is a perfect square, the Babylonian method cycles between |
||
| 221 |
// floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. |
||
| 222 |
// See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division |
||
| 223 |
// Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. |
||
| 224 |
// If you don't care whether the floor or ceil square root is returned, you can remove this statement. |
||
| 225 |
z := sub(z, lt(div(x, z), z)) |
||
| 226 |
} |
||
| 227 |
} |
||
| 228 | |||
| 229 |
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
|
||
| 230 |
/// @solidity memory-safe-assembly |
||
| 231 |
assembly {
|
||
| 232 |
// Mod x by y. Note this will return |
||
| 233 |
// 0 instead of reverting if y is zero. |
||
| 234 |
z := mod(x, y) |
||
| 235 |
} |
||
| 236 |
} |
||
| 237 | |||
| 238 |
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
|
||
| 239 |
/// @solidity memory-safe-assembly |
||
| 240 |
assembly {
|
||
| 241 |
// Divide x by y. Note this will return |
||
| 242 |
// 0 instead of reverting if y is zero. |
||
| 243 |
r := div(x, y) |
||
| 244 |
} |
||
| 245 |
} |
||
| 246 | |||
| 247 |
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
|
||
| 248 |
/// @solidity memory-safe-assembly |
||
| 249 |
assembly {
|
||
| 250 |
// Add 1 to x * y if x % y > 0. Note this will |
||
| 251 |
// return 0 instead of reverting if y is zero. |
||
| 252 |
z := add(gt(mod(x, y), 0), div(x, y)) |
||
| 253 |
} |
||
| 254 |
} |
||
| 255 |
} |
||
| 256 |
| Lines covered: | 5 / 30 (16.7%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IERC6909Claims} from "./interfaces/external/IERC6909Claims.sol";
|
||
| 5 | |||
| 6 |
/// @notice Minimalist and gas efficient standard ERC6909 implementation. |
||
| 7 |
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC6909.sol) |
||
| 8 |
/// @dev Copied from the commit at 4b47a19038b798b4a33d9749d25e570443520647 |
||
| 9 |
/// @dev This contract has been modified from the implementation at the above link. |
||
| 10 |
abstract contract ERC6909 is IERC6909Claims {
|
||
| 11 |
/*////////////////////////////////////////////////////////////// |
||
| 12 |
ERC6909 STORAGE |
||
| 13 |
//////////////////////////////////////////////////////////////*/ |
||
| 14 | |||
| 15 |
mapping(address owner => mapping(address operator => bool isOperator)) public isOperator; |
||
| 16 | |||
| 17 |
√ 49
|
⟳ 49
|
mapping(address owner => mapping(uint256 id => uint256 balance)) public balanceOf; |
| 18 | |||
| 19 |
mapping(address owner => mapping(address spender => mapping(uint256 id => uint256 amount))) public allowance; |
||
| 20 | |||
| 21 |
/*////////////////////////////////////////////////////////////// |
||
| 22 |
ERC6909 LOGIC |
||
| 23 |
//////////////////////////////////////////////////////////////*/ |
||
| 24 | |||
| 25 |
function transfer(address receiver, uint256 id, uint256 amount) public virtual returns (bool) {
|
||
| 26 |
balanceOf[msg.sender][id] -= amount; |
||
| 27 | |||
| 28 |
balanceOf[receiver][id] += amount; |
||
| 29 | |||
| 30 |
emit Transfer(msg.sender, msg.sender, receiver, id, amount); |
||
| 31 | |||
| 32 |
return true; |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public virtual returns (bool) {
|
||
| 36 |
if (msg.sender != sender && !isOperator[sender][msg.sender]) {
|
||
| 37 |
uint256 allowed = allowance[sender][msg.sender][id]; |
||
| 38 |
if (allowed != type(uint256).max) allowance[sender][msg.sender][id] = allowed - amount; |
||
| 39 |
} |
||
| 40 | |||
| 41 |
balanceOf[sender][id] -= amount; |
||
| 42 | |||
| 43 |
balanceOf[receiver][id] += amount; |
||
| 44 | |||
| 45 |
emit Transfer(msg.sender, sender, receiver, id, amount); |
||
| 46 | |||
| 47 |
return true; |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function approve(address spender, uint256 id, uint256 amount) public virtual returns (bool) {
|
||
| 51 |
allowance[msg.sender][spender][id] = amount; |
||
| 52 | |||
| 53 |
emit Approval(msg.sender, spender, id, amount); |
||
| 54 | |||
| 55 |
return true; |
||
| 56 |
} |
||
| 57 | |||
| 58 |
function setOperator(address operator, bool approved) public virtual returns (bool) {
|
||
| 59 |
isOperator[msg.sender][operator] = approved; |
||
| 60 | |||
| 61 |
emit OperatorSet(msg.sender, operator, approved); |
||
| 62 | |||
| 63 |
return true; |
||
| 64 |
} |
||
| 65 | |||
| 66 |
/*////////////////////////////////////////////////////////////// |
||
| 67 |
ERC165 LOGIC |
||
| 68 |
//////////////////////////////////////////////////////////////*/ |
||
| 69 | |||
| 70 |
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
|
||
| 71 |
return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 |
||
| 72 |
|| interfaceId == 0x0f632fb3; // ERC165 Interface ID for ERC6909 |
||
| 73 |
} |
||
| 74 | |||
| 75 |
/*////////////////////////////////////////////////////////////// |
||
| 76 |
INTERNAL MINT/BURN LOGIC |
||
| 77 |
//////////////////////////////////////////////////////////////*/ |
||
| 78 | |||
| 79 |
function _mint(address receiver, uint256 id, uint256 amount) internal virtual {
|
||
| 80 |
√ 5
|
⟳ 5
|
balanceOf[receiver][id] += amount; |
| 81 | |||
| 82 |
√ 5
|
⟳ 5
|
emit Transfer(msg.sender, address(0), receiver, id, amount); |
| 83 |
} |
||
| 84 | |||
| 85 |
function _burn(address sender, uint256 id, uint256 amount) internal virtual {
|
||
| 86 |
√ 5
|
⟳ 5
|
balanceOf[sender][id] -= amount; |
| 87 | |||
| 88 |
√ 5
|
⟳ 5
|
emit Transfer(msg.sender, sender, address(0), id, amount); |
| 89 |
} |
||
| 90 |
} |
||
| 91 |
| Lines covered: | 6 / 6 (100.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {ERC6909} from "./ERC6909.sol";
|
||
| 5 | |||
| 6 |
/// @notice ERC6909Claims inherits ERC6909 and implements an internal burnFrom function |
||
| 7 |
abstract contract ERC6909Claims is ERC6909 {
|
||
| 8 |
/// @notice Burn `amount` tokens of token type `id` from `from`. |
||
| 9 |
/// @dev if sender is not `from` they must be an operator or have sufficient allowance. |
||
| 10 |
/// @param from The address to burn tokens from. |
||
| 11 |
/// @param id The currency to burn. |
||
| 12 |
/// @param amount The amount to burn. |
||
| 13 |
function _burnFrom(address from, uint256 id, uint256 amount) internal {
|
||
| 14 |
√ 1
|
⟳ 1
|
address sender = msg.sender; |
| 15 |
√ 9
|
⟳ 9
|
if (from != sender && !isOperator[from][sender]) {
|
| 16 |
√ 2
|
⟳ 2
|
uint256 senderAllowance = allowance[from][sender][id]; |
| 17 |
√ 1
|
⟳ 1
|
if (senderAllowance != type(uint256).max) {
|
| 18 |
√ 3
|
⟳ 3
|
allowance[from][sender][id] = senderAllowance - amount; |
| 19 |
} |
||
| 20 |
} |
||
| 21 |
√ 4
|
⟳ 4
|
_burn(from, id, amount); |
| 22 |
} |
||
| 23 |
} |
||
| 24 |
| Lines covered: | 16 / 30 (53.3%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IExtsload} from "./interfaces/IExtsload.sol";
|
||
| 5 | |||
| 6 |
/// @notice Enables public storage access for efficient state retrieval by external contracts. |
||
| 7 |
/// https://eips.ethereum.org/EIPS/eip-2330#rationale |
||
| 8 |
abstract contract Extsload is IExtsload {
|
||
| 9 |
/// @inheritdoc IExtsload |
||
| 10 |
√ 1
|
⟳ 1
|
function extsload(bytes32 slot) external view returns (bytes32) {
|
| 11 |
assembly ("memory-safe") {
|
||
| 12 |
√ 2
|
⟳ 2
|
mstore(0, sload(slot)) |
| 13 |
√ 2
|
⟳ 2
|
return(0, 0x20) |
| 14 |
} |
||
| 15 |
} |
||
| 16 | |||
| 17 |
/// @inheritdoc IExtsload |
||
| 18 |
√ 1
|
⟳ 1
|
function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory) {
|
| 19 |
assembly ("memory-safe") {
|
||
| 20 |
√ 1
|
⟳ 1
|
let memptr := mload(0x40) |
| 21 |
√ 1
|
⟳ 1
|
let start := memptr |
| 22 |
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas. |
||
| 23 |
√ 2
|
⟳ 2
|
let length := shl(5, nSlots) |
| 24 |
// The abi offset of dynamic array in the returndata is 32. |
||
| 25 |
√ 2
|
⟳ 2
|
mstore(memptr, 0x20) |
| 26 |
// Store the length of the array returned |
||
| 27 |
√ 3
|
⟳ 3
|
mstore(add(memptr, 0x20), nSlots) |
| 28 |
// update memptr to the first location to hold a result |
||
| 29 |
√ 2
|
⟳ 2
|
memptr := add(memptr, 0x40) |
| 30 |
√ 2
|
⟳ 2
|
let end := add(memptr, length) |
| 31 |
for {} 1 {} {
|
||
| 32 |
√ 4
|
⟳ 4
|
mstore(memptr, sload(startSlot)) |
| 33 |
√ 4
|
⟳ 4
|
memptr := add(memptr, 0x20) |
| 34 |
√ 4
|
⟳ 4
|
startSlot := add(startSlot, 1) |
| 35 |
√ 4
|
⟳ 4
|
if iszero(lt(memptr, end)) { break }
|
| 36 |
} |
||
| 37 |
√ 3
|
⟳ 3
|
return(start, sub(end, start)) |
| 38 |
} |
||
| 39 |
} |
||
| 40 | |||
| 41 |
/// @inheritdoc IExtsload |
||
| 42 |
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
|
||
| 43 |
assembly ("memory-safe") {
|
||
| 44 |
let memptr := mload(0x40) |
||
| 45 |
let start := memptr |
||
| 46 |
// for abi encoding the response - the array will be found at 0x20 |
||
| 47 |
mstore(memptr, 0x20) |
||
| 48 |
// next we store the length of the return array |
||
| 49 |
mstore(add(memptr, 0x20), slots.length) |
||
| 50 |
// update memptr to the first location to hold an array entry |
||
| 51 |
memptr := add(memptr, 0x40) |
||
| 52 |
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas. |
||
| 53 |
let end := add(memptr, shl(5, slots.length)) |
||
| 54 |
let calldataptr := slots.offset |
||
| 55 |
for {} 1 {} {
|
||
| 56 |
mstore(memptr, sload(calldataload(calldataptr))) |
||
| 57 |
memptr := add(memptr, 0x20) |
||
| 58 |
calldataptr := add(calldataptr, 0x20) |
||
| 59 |
if iszero(lt(memptr, end)) { break }
|
||
| 60 |
} |
||
| 61 |
return(start, sub(end, start)) |
||
| 62 |
} |
||
| 63 |
} |
||
| 64 |
} |
||
| 65 |
| Lines covered: | 3 / 17 (17.6%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IExttload} from "./interfaces/IExttload.sol";
|
||
| 5 | |||
| 6 |
/// @notice Enables public transient storage access for efficient state retrieval by external contracts. |
||
| 7 |
/// https://eips.ethereum.org/EIPS/eip-2330#rationale |
||
| 8 |
abstract contract Exttload is IExttload {
|
||
| 9 |
/// @inheritdoc IExttload |
||
| 10 |
√ 1
|
⟳ 1
|
function exttload(bytes32 slot) external view returns (bytes32) {
|
| 11 |
assembly ("memory-safe") {
|
||
| 12 |
√ 2
|
⟳ 2
|
mstore(0, tload(slot)) |
| 13 |
√ 2
|
⟳ 2
|
return(0, 0x20) |
| 14 |
} |
||
| 15 |
} |
||
| 16 | |||
| 17 |
/// @inheritdoc IExttload |
||
| 18 |
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
|
||
| 19 |
assembly ("memory-safe") {
|
||
| 20 |
let memptr := mload(0x40) |
||
| 21 |
let start := memptr |
||
| 22 |
// for abi encoding the response - the array will be found at 0x20 |
||
| 23 |
mstore(memptr, 0x20) |
||
| 24 |
// next we store the length of the return array |
||
| 25 |
mstore(add(memptr, 0x20), slots.length) |
||
| 26 |
// update memptr to the first location to hold an array entry |
||
| 27 |
memptr := add(memptr, 0x40) |
||
| 28 |
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas. |
||
| 29 |
let end := add(memptr, shl(5, slots.length)) |
||
| 30 |
let calldataptr := slots.offset |
||
| 31 |
for {} 1 {} {
|
||
| 32 |
mstore(memptr, tload(calldataload(calldataptr))) |
||
| 33 |
memptr := add(memptr, 0x20) |
||
| 34 |
calldataptr := add(calldataptr, 0x20) |
||
| 35 |
if iszero(lt(memptr, end)) { break }
|
||
| 36 |
} |
||
| 37 |
return(start, sub(end, start)) |
||
| 38 |
} |
||
| 39 |
} |
||
| 40 |
} |
||
| 41 |
| Lines covered: | 3 / 4 (75.0%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {CustomRevert} from "./libraries/CustomRevert.sol";
|
||
| 5 | |||
| 6 |
/// @title Prevents delegatecall to a contract |
||
| 7 |
/// @notice Base contract that provides a modifier for preventing delegatecall to methods in a child contract |
||
| 8 |
abstract contract NoDelegateCall {
|
||
| 9 |
using CustomRevert for bytes4; |
||
| 10 | |||
| 11 |
error DelegateCallNotAllowed(); |
||
| 12 | |||
| 13 |
/// @dev The original address of this contract |
||
| 14 |
address private immutable original; |
||
| 15 | |||
| 16 |
constructor() {
|
||
| 17 |
// Immutables are computed in the init code of the contract, and then inlined into the deployed bytecode. |
||
| 18 |
// In other words, this variable won't change when it's checked at runtime. |
||
| 19 |
√ 1
|
original = address(this); |
|
| 20 |
} |
||
| 21 | |||
| 22 |
/// @dev Private method is used instead of inlining into modifier because modifiers are copied into each method, |
||
| 23 |
/// and the use of immutable means the address bytes are copied in every place the modifier is used. |
||
| 24 |
function checkNotDelegateCall() private view {
|
||
| 25 |
√ 2
|
⟳ 2
|
if (address(this) != original) DelegateCallNotAllowed.selector.revertWith(); |
| 26 |
} |
||
| 27 | |||
| 28 |
/// @notice Prevents delegatecall into the modified method |
||
| 29 |
modifier noDelegateCall() {
|
||
| 30 |
√ 4
|
⟳ 4
|
checkNotDelegateCall(); |
| 31 |
_; |
||
| 32 |
} |
||
| 33 |
} |
||
| 34 |
| Lines covered: | 107 / 117 (91.5%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Hooks} from "./libraries/Hooks.sol";
|
||
| 5 |
import {Pool} from "./libraries/Pool.sol";
|
||
| 6 |
import {SafeCast} from "./libraries/SafeCast.sol";
|
||
| 7 |
import {Position} from "./libraries/Position.sol";
|
||
| 8 |
import {LPFeeLibrary} from "./libraries/LPFeeLibrary.sol";
|
||
| 9 |
import {Currency, CurrencyLibrary} from "./types/Currency.sol";
|
||
| 10 |
import {PoolKey} from "./types/PoolKey.sol";
|
||
| 11 |
import {TickMath} from "./libraries/TickMath.sol";
|
||
| 12 |
import {NoDelegateCall} from "./NoDelegateCall.sol";
|
||
| 13 |
import {IHooks} from "./interfaces/IHooks.sol";
|
||
| 14 |
import {IPoolManager} from "./interfaces/IPoolManager.sol";
|
||
| 15 |
import {IUnlockCallback} from "./interfaces/callback/IUnlockCallback.sol";
|
||
| 16 |
import {ProtocolFees} from "./ProtocolFees.sol";
|
||
| 17 |
import {ERC6909Claims} from "./ERC6909Claims.sol";
|
||
| 18 |
import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
|
||
| 19 |
import {BalanceDelta, BalanceDeltaLibrary} from "./types/BalanceDelta.sol";
|
||
| 20 |
import {BeforeSwapDelta} from "./types/BeforeSwapDelta.sol";
|
||
| 21 |
import {Lock} from "./libraries/Lock.sol";
|
||
| 22 |
import {CurrencyDelta} from "./libraries/CurrencyDelta.sol";
|
||
| 23 |
import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
|
||
| 24 |
import {CurrencyReserves} from "./libraries/CurrencyReserves.sol";
|
||
| 25 |
import {Extsload} from "./Extsload.sol";
|
||
| 26 |
import {Exttload} from "./Exttload.sol";
|
||
| 27 |
import {CustomRevert} from "./libraries/CustomRevert.sol";
|
||
| 28 | |||
| 29 |
// 4 |
||
| 30 |
// 44 |
||
| 31 |
// 444 |
||
| 32 |
// 444 4444 |
||
| 33 |
// 4444 4444 4444 |
||
| 34 |
// 4444 4444444 4444 4 |
||
| 35 |
// 4444 44444444 4444 4 |
||
| 36 |
// 44444 4444444 4444444444444444 444444 |
||
| 37 |
// 4 44444 44444444 444444444444444444444 4444 |
||
| 38 |
// 4 44444 4444444 4444444444444444444444 44444 |
||
| 39 |
// 4 444444 4444444 44444444444444444444444 44 4 |
||
| 40 |
// 44 44444 444444 444444444444444444444 4 4 |
||
| 41 |
// 44 44444 44444 4444444444444444444 4 44 |
||
| 42 |
// 44 4444 44 444444444444444 444 |
||
| 43 |
// 444 4444 4444444 |
||
| 44 |
// 4444444444444 44 4 |
||
| 45 |
// 44444444444 444444 444444444 44 |
||
| 46 |
// 444444 4444 4444 4444444444 44 |
||
| 47 |
// 4444 44 44 4 44444444444 |
||
| 48 |
// 44444 444444444 444444444444 4444 |
||
| 49 |
// 44444 44444444 4444 44444444 444444 |
||
| 50 |
// 44444 4444 444444444 44444444 |
||
| 51 |
// 44444 4444 44444444 4444444444 |
||
| 52 |
// 44444 4444 444444444 444444444444 |
||
| 53 |
// 44444 4444 44444444 444444444444 |
||
| 54 |
// 4444444 4444 44444444 4444444 |
||
| 55 |
// 4444444 44444 44444444 4444444 |
||
| 56 |
// 44444444 44444444444444444444444444444 4444 |
||
| 57 |
// 4444444444 44444444444444444444444444444 444 |
||
| 58 |
// 444444444444 444444444444444444444444444444 444 444 |
||
| 59 |
// 44444444444444 444444444 44444 |
||
| 60 |
// 44444 44444444444 444 44444444 444444 |
||
| 61 |
// 44444 4444444444 4444444444 444444 44444444 444444444444 |
||
| 62 |
// 444444444444444 4444 444444 4444444 44444444 444444444444 |
||
| 63 |
// 444444444444444 444 444444 444444 44444444 44444444444 |
||
| 64 |
// 4444444444444 4444 444444 4444 4444444444 |
||
| 65 |
// 444444444444 4 44444 4444 444444444 |
||
| 66 |
// 44444444444 444444 444 44444444 |
||
| 67 |
// 44444444 444444 4444 4444444 |
||
| 68 |
// 44444 444 44444 |
||
| 69 |
// 44444 444 4 4444 |
||
| 70 |
// 44444 444 44 444 |
||
| 71 |
// 44444 444 4444 |
||
| 72 |
// 444444 44444 444 |
||
| 73 |
// 444444444 444 |
||
| 74 |
// 44444 444 |
||
| 75 |
// 444 |
||
| 76 | |||
| 77 |
/// @title PoolManager |
||
| 78 |
/// @notice Holds the state for all pools |
||
| 79 |
contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload, Exttload {
|
||
| 80 |
using PoolIdLibrary for PoolKey; |
||
| 81 |
using SafeCast for *; |
||
| 82 |
using Pool for *; |
||
| 83 |
using Hooks for IHooks; |
||
| 84 |
using Position for mapping(bytes32 => Position.Info); |
||
| 85 |
using CurrencyDelta for Currency; |
||
| 86 |
using LPFeeLibrary for uint24; |
||
| 87 |
using CurrencyReserves for Currency; |
||
| 88 |
using CustomRevert for bytes4; |
||
| 89 | |||
| 90 |
/// @inheritdoc IPoolManager |
||
| 91 |
int24 public constant MAX_TICK_SPACING = TickMath.MAX_TICK_SPACING; |
||
| 92 | |||
| 93 |
/// @inheritdoc IPoolManager |
||
| 94 |
√ 4
|
⟳ 4
|
int24 public constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING; |
| 95 | |||
| 96 |
mapping(PoolId id => Pool.State) internal _pools; |
||
| 97 | |||
| 98 |
√ 2
|
constructor(uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {}
|
|
| 99 | |||
| 100 |
/// @notice This will revert if the contract is locked |
||
| 101 |
modifier onlyWhenUnlocked() {
|
||
| 102 |
if (!Lock.isUnlocked()) ManagerLocked.selector.revertWith(); |
||
| 103 |
√ 2
|
⟳ 2
|
_; |
| 104 |
} |
||
| 105 | |||
| 106 |
/// @inheritdoc IPoolManager |
||
| 107 |
√ 1
|
⟳ 1
|
function unlock(bytes calldata data) external override returns (bytes memory result) {
|
| 108 |
if (Lock.isUnlocked()) AlreadyUnlocked.selector.revertWith(); |
||
| 109 | |||
| 110 |
√ 1
|
⟳ 1
|
Lock.unlock(); |
| 111 | |||
| 112 |
// the caller does everything in this callback, including paying what they owe via calls to settle |
||
| 113 |
√ 6
|
⟳ 6
|
result = IUnlockCallback(msg.sender).unlockCallback(data); |
| 114 | |||
| 115 |
√ 1
|
⟳ 2
|
if (NonZeroDeltaCount.read() != 0) CurrencyNotSettled.selector.revertWith(); |
| 116 |
√ 1
|
⟳ 1
|
Lock.lock(); |
| 117 |
} |
||
| 118 | |||
| 119 |
/// @inheritdoc IPoolManager |
||
| 120 |
function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) |
||
| 121 |
external |
||
| 122 |
noDelegateCall |
||
| 123 |
√ 1
|
⟳ 1
|
returns (int24 tick) |
| 124 |
{
|
||
| 125 |
// see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large |
||
| 126 |
√ 4
|
⟳ 10
|
if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing); |
| 127 |
√ 1
|
⟳ 7
|
if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing); |
| 128 |
√ 6
|
⟳ 6
|
if (key.currency0 >= key.currency1) {
|
| 129 |
CurrenciesOutOfOrderOrEqual.selector.revertWith( |
||
| 130 |
Currency.unwrap(key.currency0), Currency.unwrap(key.currency1) |
||
| 131 |
); |
||
| 132 |
} |
||
| 133 |
√ 2
|
⟳ 8
|
if (!key.hooks.isValidHookAddress(key.fee)) Hooks.HookAddressNotValid.selector.revertWith(address(key.hooks)); |
| 134 | |||
| 135 |
√ 2
|
⟳ 2
|
uint24 lpFee = key.fee.getInitialLPFee(); |
| 136 | |||
| 137 |
√ 8
|
⟳ 8
|
key.hooks.beforeInitialize(key, sqrtPriceX96, hookData); |
| 138 | |||
| 139 |
PoolId id = key.toId(); |
||
| 140 |
√ 3
|
⟳ 3
|
(, uint24 protocolFee) = _fetchProtocolFee(key); |
| 141 | |||
| 142 |
√ 3
|
⟳ 3
|
tick = _pools[id].initialize(sqrtPriceX96, protocolFee, lpFee); |
| 143 | |||
| 144 |
√ 8
|
⟳ 8
|
key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData); |
| 145 | |||
| 146 |
// emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller |
||
| 147 |
// the key's fee may be a static fee or a sentinel to denote a dynamic fee. |
||
| 148 |
√ 6
|
⟳ 6
|
emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks); |
| 149 |
} |
||
| 150 | |||
| 151 |
/// @inheritdoc IPoolManager |
||
| 152 |
function modifyLiquidity( |
||
| 153 |
PoolKey memory key, |
||
| 154 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 155 |
bytes calldata hookData |
||
| 156 |
√ 2
|
⟳ 2
|
) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) {
|
| 157 |
√ 1
|
⟳ 1
|
PoolId id = key.toId(); |
| 158 |
Pool.State storage pool = _getPool(id); |
||
| 159 |
√ 1
|
⟳ 1
|
pool.checkPoolInitialized(); |
| 160 | |||
| 161 |
√ 8
|
⟳ 8
|
key.hooks.beforeModifyLiquidity(key, params, hookData); |
| 162 | |||
| 163 |
√ 1
|
⟳ 1
|
BalanceDelta principalDelta; |
| 164 |
√ 2
|
⟳ 2
|
(principalDelta, feesAccrued) = pool.modifyLiquidity( |
| 165 |
Pool.ModifyLiquidityParams({
|
||
| 166 |
√ 1
|
⟳ 1
|
owner: msg.sender, |
| 167 |
√ 1
|
⟳ 1
|
tickLower: params.tickLower, |
| 168 |
√ 1
|
⟳ 1
|
tickUpper: params.tickUpper, |
| 169 |
√ 1
|
⟳ 1
|
liquidityDelta: params.liquidityDelta.toInt128(), |
| 170 |
√ 5
|
⟳ 5
|
tickSpacing: key.tickSpacing, |
| 171 |
√ 3
|
⟳ 3
|
salt: params.salt |
| 172 |
}) |
||
| 173 |
); |
||
| 174 | |||
| 175 |
// fee delta and principal delta are both accrued to the caller |
||
| 176 |
√ 4
|
⟳ 4
|
callerDelta = principalDelta + feesAccrued; |
| 177 | |||
| 178 |
// event is emitted before the afterModifyLiquidity call to ensure events are always emitted in order |
||
| 179 |
√ 5
|
⟳ 5
|
emit ModifyLiquidity(id, msg.sender, params.tickLower, params.tickUpper, params.liquidityDelta); |
| 180 | |||
| 181 |
√ 2
|
⟳ 2
|
BalanceDelta hookDelta; |
| 182 |
√ 9
|
⟳ 9
|
(callerDelta, hookDelta) = key.hooks.afterModifyLiquidity(key, params, callerDelta, hookData); |
| 183 | |||
| 184 |
// if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0 |
||
| 185 |
if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks)); |
||
| 186 | |||
| 187 |
√ 4
|
⟳ 4
|
_accountPoolBalanceDelta(key, callerDelta, msg.sender); |
| 188 |
} |
||
| 189 | |||
| 190 |
/// @inheritdoc IPoolManager |
||
| 191 |
function swap(PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData) |
||
| 192 |
external |
||
| 193 |
onlyWhenUnlocked |
||
| 194 |
noDelegateCall |
||
| 195 |
√ 1
|
⟳ 1
|
returns (BalanceDelta swapDelta) |
| 196 |
{
|
||
| 197 |
√ 2
|
⟳ 3
|
if (params.amountSpecified == 0) SwapAmountCannotBeZero.selector.revertWith(); |
| 198 |
√ 1
|
⟳ 1
|
PoolId id = key.toId(); |
| 199 |
Pool.State storage pool = _getPool(id); |
||
| 200 |
√ 1
|
⟳ 1
|
pool.checkPoolInitialized(); |
| 201 | |||
| 202 |
√ 6
|
⟳ 6
|
BeforeSwapDelta beforeSwapDelta; |
| 203 |
{
|
||
| 204 |
int256 amountToSwap; |
||
| 205 |
uint24 lpFeeOverride; |
||
| 206 |
√ 8
|
⟳ 8
|
(amountToSwap, beforeSwapDelta, lpFeeOverride) = key.hooks.beforeSwap(key, params, hookData); |
| 207 | |||
| 208 |
// execute swap, account protocol fees, and emit swap event |
||
| 209 |
// _swap is needed to avoid stack too deep error |
||
| 210 |
√ 2
|
⟳ 2
|
swapDelta = _swap( |
| 211 |
√ 1
|
⟳ 1
|
pool, |
| 212 |
√ 1
|
⟳ 1
|
id, |
| 213 |
Pool.SwapParams({
|
||
| 214 |
√ 1
|
⟳ 1
|
tickSpacing: key.tickSpacing, |
| 215 |
√ 1
|
⟳ 1
|
zeroForOne: params.zeroForOne, |
| 216 |
√ 1
|
⟳ 1
|
amountSpecified: amountToSwap, |
| 217 |
√ 1
|
⟳ 1
|
sqrtPriceLimitX96: params.sqrtPriceLimitX96, |
| 218 |
√ 1
|
⟳ 1
|
lpFeeOverride: lpFeeOverride |
| 219 |
}), |
||
| 220 |
√ 4
|
⟳ 4
|
params.zeroForOne ? key.currency0 : key.currency1 // input token |
| 221 |
); |
||
| 222 |
} |
||
| 223 | |||
| 224 |
√ 2
|
⟳ 2
|
BalanceDelta hookDelta; |
| 225 |
√ 9
|
⟳ 9
|
(swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, beforeSwapDelta); |
| 226 | |||
| 227 |
// if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0 |
||
| 228 |
if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks)); |
||
| 229 | |||
| 230 |
√ 4
|
⟳ 4
|
_accountPoolBalanceDelta(key, swapDelta, msg.sender); |
| 231 |
} |
||
| 232 | |||
| 233 |
/// @notice Internal swap function to execute a swap, take protocol fees on input token, and emit the swap event |
||
| 234 |
function _swap(Pool.State storage pool, PoolId id, Pool.SwapParams memory params, Currency inputCurrency) |
||
| 235 |
internal |
||
| 236 |
√ 5
|
⟳ 5
|
returns (BalanceDelta) |
| 237 |
{
|
||
| 238 |
√ 2
|
⟳ 2
|
(BalanceDelta delta, uint256 feeForProtocol, uint24 swapFee, Pool.SwapState memory state) = pool.swap(params); |
| 239 | |||
| 240 |
// the fee is on the input currency |
||
| 241 |
√ 3
|
⟳ 3
|
if (feeForProtocol > 0) _updateProtocolFees(inputCurrency, feeForProtocol); |
| 242 | |||
| 243 |
// event is emitted before the afterSwap call to ensure events are always emitted in order |
||
| 244 |
emit Swap( |
||
| 245 |
√ 20
|
⟳ 20
|
id, msg.sender, delta.amount0(), delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee |
| 246 |
); |
||
| 247 | |||
| 248 |
√ 2
|
⟳ 2
|
return delta; |
| 249 |
} |
||
| 250 | |||
| 251 |
/// @inheritdoc IPoolManager |
||
| 252 |
function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) |
||
| 253 |
external |
||
| 254 |
onlyWhenUnlocked |
||
| 255 |
noDelegateCall |
||
| 256 |
√ 1
|
⟳ 1
|
returns (BalanceDelta delta) |
| 257 |
{
|
||
| 258 |
√ 2
|
⟳ 2
|
Pool.State storage pool = _getPool(key.toId()); |
| 259 |
√ 1
|
⟳ 1
|
pool.checkPoolInitialized(); |
| 260 | |||
| 261 |
√ 9
|
⟳ 9
|
key.hooks.beforeDonate(key, amount0, amount1, hookData); |
| 262 | |||
| 263 |
√ 3
|
⟳ 3
|
delta = pool.donate(amount0, amount1); |
| 264 | |||
| 265 |
√ 4
|
⟳ 4
|
_accountPoolBalanceDelta(key, delta, msg.sender); |
| 266 | |||
| 267 |
√ 9
|
⟳ 9
|
key.hooks.afterDonate(key, amount0, amount1, hookData); |
| 268 |
} |
||
| 269 | |||
| 270 |
/// @inheritdoc IPoolManager |
||
| 271 |
function sync(Currency currency) external {
|
||
| 272 |
√ 1
|
⟳ 1
|
CurrencyReserves.requireNotSynced(); |
| 273 |
√ 3
|
⟳ 3
|
if (currency.isNative()) return; |
| 274 |
√ 2
|
⟳ 2
|
uint256 balance = currency.balanceOfSelf(); |
| 275 |
√ 3
|
⟳ 3
|
CurrencyReserves.syncCurrencyAndReserves(currency, balance); |
| 276 |
} |
||
| 277 | |||
| 278 |
/// @inheritdoc IPoolManager |
||
| 279 |
function take(Currency currency, address to, uint256 amount) external onlyWhenUnlocked {
|
||
| 280 |
unchecked {
|
||
| 281 |
// negation must be safe as amount is not negative |
||
| 282 |
√ 4
|
⟳ 4
|
_accountDelta(currency, -(amount.toInt128()), msg.sender); |
| 283 |
√ 6
|
⟳ 6
|
currency.transfer(to, amount); |
| 284 |
} |
||
| 285 |
} |
||
| 286 | |||
| 287 |
/// @inheritdoc IPoolManager |
||
| 288 |
√ 1
|
⟳ 1
|
function settle() external payable onlyWhenUnlocked returns (uint256 paid) {
|
| 289 |
√ 2
|
⟳ 2
|
return _settle(msg.sender); |
| 290 |
} |
||
| 291 | |||
| 292 |
/// @inheritdoc IPoolManager |
||
| 293 |
√ 1
|
⟳ 1
|
function settleFor(address recipient) external payable onlyWhenUnlocked returns (uint256 paid) {
|
| 294 |
√ 2
|
⟳ 2
|
return _settle(recipient); |
| 295 |
} |
||
| 296 | |||
| 297 |
/// @inheritdoc IPoolManager |
||
| 298 |
function clear(Currency currency, uint256 amount) external onlyWhenUnlocked {
|
||
| 299 |
√ 5
|
⟳ 5
|
int256 current = currency.getDelta(msg.sender); |
| 300 |
// Because input is `uint256`, only positive amounts can be cleared. |
||
| 301 |
√ 1
|
⟳ 1
|
int128 amountDelta = amount.toInt128(); |
| 302 |
√ 2
|
⟳ 3
|
if (amountDelta != current) MustClearExactPositiveDelta.selector.revertWith(); |
| 303 |
√ 4
|
⟳ 4
|
_accountDelta(currency, -(amountDelta), msg.sender); |
| 304 |
} |
||
| 305 | |||
| 306 |
/// @inheritdoc IPoolManager |
||
| 307 |
function mint(address to, uint256 id, uint256 amount) external onlyWhenUnlocked {
|
||
| 308 |
unchecked {
|
||
| 309 |
√ 2
|
⟳ 2
|
Currency currency = CurrencyLibrary.fromId(id); |
| 310 |
// negation must be safe as amount is not negative |
||
| 311 |
√ 1
|
⟳ 1
|
_accountDelta(currency, -(amount.toInt128()), msg.sender); |
| 312 |
√ 6
|
⟳ 6
|
_mint(to, currency.toId(), amount); |
| 313 |
} |
||
| 314 |
} |
||
| 315 | |||
| 316 |
/// @inheritdoc IPoolManager |
||
| 317 |
function burn(address from, uint256 id, uint256 amount) external onlyWhenUnlocked {
|
||
| 318 |
√ 2
|
⟳ 2
|
Currency currency = CurrencyLibrary.fromId(id); |
| 319 |
√ 1
|
⟳ 1
|
_accountDelta(currency, amount.toInt128(), msg.sender); |
| 320 |
√ 6
|
⟳ 6
|
_burnFrom(from, currency.toId(), amount); |
| 321 |
} |
||
| 322 | |||
| 323 |
/// @inheritdoc IPoolManager |
||
| 324 |
function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external {
|
||
| 325 |
⟳ 4
|
if (!key.fee.isDynamicFee() || msg.sender != address(key.hooks)) {
|
|
| 326 |
⟳ 1
|
UnauthorizedDynamicLPFeeUpdate.selector.revertWith(); |
|
| 327 |
} |
||
| 328 |
newDynamicLPFee.validate(); |
||
| 329 |
PoolId id = key.toId(); |
||
| 330 |
_pools[id].setLPFee(newDynamicLPFee); |
||
| 331 |
} |
||
| 332 | |||
| 333 |
√ 1
|
⟳ 1
|
function _settle(address recipient) internal returns (uint256 paid) {
|
| 334 |
Currency currency = CurrencyReserves.getSyncedCurrency(); |
||
| 335 |
// If not previously synced, expects native currency to be settled because CurrencyLibrary.NATIVE == address(0) |
||
| 336 |
√ 3
|
⟳ 3
|
if (currency.isNative()) {
|
| 337 |
√ 1
|
⟳ 1
|
paid = msg.value; |
| 338 |
} else {
|
||
| 339 |
√ 1
|
⟳ 2
|
if (msg.value > 0) NonZeroNativeValue.selector.revertWith(); |
| 340 |
// Reserves are guaranteed to be set, because currency and reserves are always set together |
||
| 341 |
√ 1
|
⟳ 1
|
uint256 reservesBefore = CurrencyReserves.getSyncedReserves(); |
| 342 |
√ 4
|
⟳ 4
|
uint256 reservesNow = currency.balanceOfSelf(); |
| 343 |
√ 1
|
⟳ 1
|
paid = reservesNow - reservesBefore; |
| 344 |
√ 1
|
⟳ 1
|
CurrencyReserves.resetCurrency(); |
| 345 |
} |
||
| 346 |
√ 4
|
⟳ 4
|
_accountDelta(currency, paid.toInt128(), recipient); |
| 347 |
} |
||
| 348 | |||
| 349 |
/// @notice Adds a balance delta in a currency for a target address |
||
| 350 |
function _accountDelta(Currency currency, int128 delta, address target) internal {
|
||
| 351 |
√ 2
|
⟳ 2
|
if (delta == 0) return; |
| 352 | |||
| 353 |
√ 8
|
⟳ 8
|
(int256 previous, int256 next) = currency.applyDelta(target, delta); |
| 354 | |||
| 355 |
√ 2
|
⟳ 2
|
if (next == 0) {
|
| 356 |
√ 1
|
⟳ 1
|
NonZeroDeltaCount.decrement(); |
| 357 |
√ 2
|
⟳ 4
|
} else if (previous == 0) {
|
| 358 |
√ 1
|
⟳ 2
|
NonZeroDeltaCount.increment(); |
| 359 |
} |
||
| 360 |
} |
||
| 361 | |||
| 362 |
/// @notice Accounts the deltas of 2 currencies to a target address |
||
| 363 |
function _accountPoolBalanceDelta(PoolKey memory key, BalanceDelta delta, address target) internal {
|
||
| 364 |
√ 7
|
⟳ 7
|
_accountDelta(key.currency0, delta.amount0(), target); |
| 365 |
√ 2
|
⟳ 2
|
_accountDelta(key.currency1, delta.amount1(), target); |
| 366 |
} |
||
| 367 | |||
| 368 |
/// @notice Implementation of the _getPool function defined in ProtocolFees |
||
| 369 |
√ 2
|
⟳ 2
|
function _getPool(PoolId id) internal view override returns (Pool.State storage) {
|
| 370 |
√ 4
|
⟳ 4
|
return _pools[id]; |
| 371 |
} |
||
| 372 |
} |
||
| 373 |
| Lines covered: | 30 / 30 (100.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {Currency} from "./types/Currency.sol";
|
||
| 5 |
import {IProtocolFeeController} from "./interfaces/IProtocolFeeController.sol";
|
||
| 6 |
import {IProtocolFees} from "./interfaces/IProtocolFees.sol";
|
||
| 7 |
import {PoolKey} from "./types/PoolKey.sol";
|
||
| 8 |
import {ProtocolFeeLibrary} from "./libraries/ProtocolFeeLibrary.sol";
|
||
| 9 |
import {Owned} from "solmate/auth/Owned.sol";
|
||
| 10 |
import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
|
||
| 11 |
import {Pool} from "./libraries/Pool.sol";
|
||
| 12 |
import {CustomRevert} from "./libraries/CustomRevert.sol";
|
||
| 13 | |||
| 14 |
/// @notice Contract handling the setting and accrual of protocol fees |
||
| 15 |
abstract contract ProtocolFees is IProtocolFees, Owned {
|
||
| 16 |
using ProtocolFeeLibrary for uint24; |
||
| 17 |
using PoolIdLibrary for PoolKey; |
||
| 18 |
using Pool for Pool.State; |
||
| 19 |
using CustomRevert for bytes4; |
||
| 20 | |||
| 21 |
/// @inheritdoc IProtocolFees |
||
| 22 |
√ 27
|
⟳ 27
|
mapping(Currency currency => uint256 amount) public protocolFeesAccrued; |
| 23 | |||
| 24 |
/// @inheritdoc IProtocolFees |
||
| 25 |
√ 15
|
⟳ 15
|
IProtocolFeeController public protocolFeeController; |
| 26 | |||
| 27 |
uint256 private immutable controllerGasLimit; |
||
| 28 | |||
| 29 |
√ 3
|
constructor(uint256 _controllerGasLimit) Owned(msg.sender) {
|
|
| 30 |
√ 2
|
controllerGasLimit = _controllerGasLimit; |
|
| 31 |
} |
||
| 32 | |||
| 33 |
/// @inheritdoc IProtocolFees |
||
| 34 |
function setProtocolFeeController(IProtocolFeeController controller) external onlyOwner {
|
||
| 35 |
√ 1
|
⟳ 1
|
protocolFeeController = controller; |
| 36 |
√ 5
|
⟳ 5
|
emit ProtocolFeeControllerUpdated(address(controller)); |
| 37 |
} |
||
| 38 | |||
| 39 |
/// @inheritdoc IProtocolFees |
||
| 40 |
function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external {
|
||
| 41 |
√ 5
|
⟳ 5
|
if (msg.sender != address(protocolFeeController)) InvalidCaller.selector.revertWith(); |
| 42 |
⟳ 1
|
if (!newProtocolFee.isValidProtocolFee()) ProtocolFeeTooLarge.selector.revertWith(newProtocolFee); |
|
| 43 |
PoolId id = key.toId(); |
||
| 44 |
√ 2
|
⟳ 2
|
_getPool(id).setProtocolFee(newProtocolFee); |
| 45 |
√ 2
|
⟳ 2
|
emit ProtocolFeeUpdated(id, newProtocolFee); |
| 46 |
} |
||
| 47 | |||
| 48 |
/// @inheritdoc IProtocolFees |
||
| 49 |
function collectProtocolFees(address recipient, Currency currency, uint256 amount) |
||
| 50 |
external |
||
| 51 |
√ 2
|
⟳ 2
|
returns (uint256 amountCollected) |
| 52 |
{
|
||
| 53 |
√ 5
|
⟳ 5
|
if (msg.sender != address(protocolFeeController)) InvalidCaller.selector.revertWith(); |
| 54 | |||
| 55 |
√ 4
|
⟳ 4
|
amountCollected = (amount == 0) ? protocolFeesAccrued[currency] : amount; |
| 56 |
√ 1
|
⟳ 1
|
protocolFeesAccrued[currency] -= amountCollected; |
| 57 |
√ 6
|
⟳ 6
|
currency.transfer(recipient, amountCollected); |
| 58 |
} |
||
| 59 | |||
| 60 |
/// @dev abstract internal function to allow the ProtocolFees contract to access pool state |
||
| 61 |
/// @dev this is overriden in PoolManager.sol to give access to the _pools mapping |
||
| 62 |
function _getPool(PoolId id) internal virtual returns (Pool.State storage); |
||
| 63 | |||
| 64 |
/// @notice Fetch the protocol fees for a given pool, returning false if the call fails or the returned fees are invalid. |
||
| 65 |
/// @dev to prevent an invalid protocol fee controller from blocking pools from being initialized |
||
| 66 |
/// the success of this function is NOT checked on initialize and if the call fails, the protocol fees are set to 0. |
||
| 67 |
/// @dev the success of this function must be checked when called in setProtocolFee |
||
| 68 |
√ 4
|
⟳ 4
|
function _fetchProtocolFee(PoolKey memory key) internal returns (bool success, uint24 protocolFee) {
|
| 69 |
√ 3
|
⟳ 3
|
if (address(protocolFeeController) != address(0)) {
|
| 70 |
// note that EIP-150 mandates that calls requesting more than 63/64ths of remaining gas |
||
| 71 |
// will be allotted no more than this amount, so controllerGasLimit must be set with this |
||
| 72 |
// in mind. |
||
| 73 |
√ 2
|
⟳ 2
|
if (gasleft() < controllerGasLimit) ProtocolFeeCannotBeFetched.selector.revertWith(); |
| 74 | |||
| 75 |
√ 4
|
⟳ 4
|
uint256 gasLimit = controllerGasLimit; |
| 76 |
√ 5
|
⟳ 5
|
address toAddress = address(protocolFeeController); |
| 77 | |||
| 78 |
√ 2
|
⟳ 2
|
bytes memory data = abi.encodeCall(IProtocolFeeController.protocolFeeForPool, (key)); |
| 79 |
uint256 returnData; |
||
| 80 |
assembly ("memory-safe") {
|
||
| 81 |
√ 5
|
⟳ 5
|
success := call(gasLimit, toAddress, 0, add(data, 0x20), mload(data), 0, 0) |
| 82 | |||
| 83 |
// success if return data size is 32 bytes |
||
| 84 |
// only load the return value if it is 32 bytes to prevent gas griefing |
||
| 85 |
√ 2
|
⟳ 2
|
success := and(success, eq(returndatasize(), 32)) |
| 86 | |||
| 87 |
// load the return data if success is true |
||
| 88 |
if success {
|
||
| 89 |
√ 1
|
⟳ 1
|
let fmp := mload(0x40) |
| 90 |
√ 3
|
⟳ 3
|
returndatacopy(fmp, 0, returndatasize()) |
| 91 |
√ 1
|
⟳ 1
|
returnData := mload(fmp) |
| 92 |
√ 2
|
⟳ 2
|
mstore(fmp, 0) |
| 93 |
} |
||
| 94 |
} |
||
| 95 | |||
| 96 |
// Ensure return data does not overflow a uint24 and that the underlying fees are within bounds. |
||
| 97 |
√ 3
|
⟳ 3
|
(success, protocolFee) = success && (returnData == uint24(returnData)) |
| 98 |
√ 3
|
⟳ 3
|
&& uint24(returnData).isValidProtocolFee() ? (true, uint24(returnData)) : (false, 0); |
| 99 |
} |
||
| 100 |
} |
||
| 101 | |||
| 102 |
function _updateProtocolFees(Currency currency, uint256 amount) internal {
|
||
| 103 |
unchecked {
|
||
| 104 |
√ 1
|
⟳ 1
|
protocolFeesAccrued[currency] += amount; |
| 105 |
} |
||
| 106 |
} |
||
| 107 |
} |
||
| 108 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @notice Interface for functions to access any storage slot in a contract |
||
| 5 |
interface IExtsload {
|
||
| 6 |
/// @notice Called by external contracts to access granular pool state |
||
| 7 |
/// @param slot Key of slot to sload |
||
| 8 |
/// @return value The value of the slot as bytes32 |
||
| 9 |
function extsload(bytes32 slot) external view returns (bytes32 value); |
||
| 10 | |||
| 11 |
/// @notice Called by external contracts to access granular pool state |
||
| 12 |
/// @param startSlot Key of slot to start sloading from |
||
| 13 |
/// @param nSlots Number of slots to load into return value |
||
| 14 |
/// @return values List of loaded values. |
||
| 15 |
function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values); |
||
| 16 | |||
| 17 |
/// @notice Called by external contracts to access sparse pool state |
||
| 18 |
/// @param slots List of slots to SLOAD from. |
||
| 19 |
/// @return values List of loaded values. |
||
| 20 |
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values); |
||
| 21 |
} |
||
| 22 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
/// @notice Interface for functions to access any transient storage slot in a contract |
||
| 5 |
interface IExttload {
|
||
| 6 |
/// @notice Called by external contracts to access transient storage of the contract |
||
| 7 |
/// @param slot Key of slot to tload |
||
| 8 |
/// @return value The value of the slot as bytes32 |
||
| 9 |
function exttload(bytes32 slot) external view returns (bytes32 value); |
||
| 10 | |||
| 11 |
/// @notice Called by external contracts to access sparse transient pool state |
||
| 12 |
/// @param slots List of slots to tload |
||
| 13 |
/// @return values List of loaded values |
||
| 14 |
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values); |
||
| 15 |
} |
||
| 16 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 5 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 6 |
import {IPoolManager} from "./IPoolManager.sol";
|
||
| 7 |
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
|
||
| 8 | |||
| 9 |
/// @notice The PoolManager contract decides whether to invoke specific hooks by inspecting the leading bits |
||
| 10 |
/// of the hooks contract address. For example, a 1 bit in the first bit of the address will |
||
| 11 |
/// cause the 'before swap' hook to be invoked. See the Hooks library for the full spec. |
||
| 12 |
/// @dev Should only be callable by the v4 PoolManager. |
||
| 13 |
interface IHooks {
|
||
| 14 |
/// @notice The hook called before the state of a pool is initialized |
||
| 15 |
/// @param sender The initial msg.sender for the initialize call |
||
| 16 |
/// @param key The key for the pool being initialized |
||
| 17 |
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 |
||
| 18 |
/// @param hookData Arbitrary data handed into the PoolManager by the initializer to be be passed on to the hook |
||
| 19 |
/// @return bytes4 The function selector for the hook |
||
| 20 |
function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, bytes calldata hookData) |
||
| 21 |
external |
||
| 22 |
returns (bytes4); |
||
| 23 | |||
| 24 |
/// @notice The hook called after the state of a pool is initialized |
||
| 25 |
/// @param sender The initial msg.sender for the initialize call |
||
| 26 |
/// @param key The key for the pool being initialized |
||
| 27 |
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 |
||
| 28 |
/// @param tick The current tick after the state of a pool is initialized |
||
| 29 |
/// @param hookData Arbitrary data handed into the PoolManager by the initializer to be be passed on to the hook |
||
| 30 |
/// @return bytes4 The function selector for the hook |
||
| 31 |
function afterInitialize( |
||
| 32 |
address sender, |
||
| 33 |
PoolKey calldata key, |
||
| 34 |
uint160 sqrtPriceX96, |
||
| 35 |
int24 tick, |
||
| 36 |
bytes calldata hookData |
||
| 37 |
) external returns (bytes4); |
||
| 38 | |||
| 39 |
/// @notice The hook called before liquidity is added |
||
| 40 |
/// @param sender The initial msg.sender for the add liquidity call |
||
| 41 |
/// @param key The key for the pool |
||
| 42 |
/// @param params The parameters for adding liquidity |
||
| 43 |
/// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook |
||
| 44 |
/// @return bytes4 The function selector for the hook |
||
| 45 |
function beforeAddLiquidity( |
||
| 46 |
address sender, |
||
| 47 |
PoolKey calldata key, |
||
| 48 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 49 |
bytes calldata hookData |
||
| 50 |
) external returns (bytes4); |
||
| 51 | |||
| 52 |
/// @notice The hook called after liquidity is added |
||
| 53 |
/// @param sender The initial msg.sender for the add liquidity call |
||
| 54 |
/// @param key The key for the pool |
||
| 55 |
/// @param params The parameters for adding liquidity |
||
| 56 |
/// @param delta The caller's balance delta after adding liquidity |
||
| 57 |
/// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook |
||
| 58 |
/// @return bytes4 The function selector for the hook |
||
| 59 |
/// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency |
||
| 60 |
function afterAddLiquidity( |
||
| 61 |
address sender, |
||
| 62 |
PoolKey calldata key, |
||
| 63 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 64 |
BalanceDelta delta, |
||
| 65 |
bytes calldata hookData |
||
| 66 |
) external returns (bytes4, BalanceDelta); |
||
| 67 | |||
| 68 |
/// @notice The hook called before liquidity is removed |
||
| 69 |
/// @param sender The initial msg.sender for the remove liquidity call |
||
| 70 |
/// @param key The key for the pool |
||
| 71 |
/// @param params The parameters for removing liquidity |
||
| 72 |
/// @param hookData Arbitrary data handed into the PoolManager by the liquidty provider to be be passed on to the hook |
||
| 73 |
/// @return bytes4 The function selector for the hook |
||
| 74 |
function beforeRemoveLiquidity( |
||
| 75 |
address sender, |
||
| 76 |
PoolKey calldata key, |
||
| 77 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 78 |
bytes calldata hookData |
||
| 79 |
) external returns (bytes4); |
||
| 80 | |||
| 81 |
/// @notice The hook called after liquidity is removed |
||
| 82 |
/// @param sender The initial msg.sender for the remove liquidity call |
||
| 83 |
/// @param key The key for the pool |
||
| 84 |
/// @param params The parameters for removing liquidity |
||
| 85 |
/// @param delta The caller's balance delta after removing liquidity |
||
| 86 |
/// @param hookData Arbitrary data handed into the PoolManager by the liquidty provider to be be passed on to the hook |
||
| 87 |
/// @return bytes4 The function selector for the hook |
||
| 88 |
/// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency |
||
| 89 |
function afterRemoveLiquidity( |
||
| 90 |
address sender, |
||
| 91 |
PoolKey calldata key, |
||
| 92 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 93 |
BalanceDelta delta, |
||
| 94 |
bytes calldata hookData |
||
| 95 |
) external returns (bytes4, BalanceDelta); |
||
| 96 | |||
| 97 |
/// @notice The hook called before a swap |
||
| 98 |
/// @param sender The initial msg.sender for the swap call |
||
| 99 |
/// @param key The key for the pool |
||
| 100 |
/// @param params The parameters for the swap |
||
| 101 |
/// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook |
||
| 102 |
/// @return bytes4 The function selector for the hook |
||
| 103 |
/// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency |
||
| 104 |
/// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million) |
||
| 105 |
function beforeSwap( |
||
| 106 |
address sender, |
||
| 107 |
PoolKey calldata key, |
||
| 108 |
IPoolManager.SwapParams calldata params, |
||
| 109 |
bytes calldata hookData |
||
| 110 |
) external returns (bytes4, BeforeSwapDelta, uint24); |
||
| 111 | |||
| 112 |
/// @notice The hook called after a swap |
||
| 113 |
/// @param sender The initial msg.sender for the swap call |
||
| 114 |
/// @param key The key for the pool |
||
| 115 |
/// @param params The parameters for the swap |
||
| 116 |
/// @param delta The amount owed to the caller (positive) or owed to the pool (negative) |
||
| 117 |
/// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook |
||
| 118 |
/// @return bytes4 The function selector for the hook |
||
| 119 |
/// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency |
||
| 120 |
function afterSwap( |
||
| 121 |
address sender, |
||
| 122 |
PoolKey calldata key, |
||
| 123 |
IPoolManager.SwapParams calldata params, |
||
| 124 |
BalanceDelta delta, |
||
| 125 |
bytes calldata hookData |
||
| 126 |
) external returns (bytes4, int128); |
||
| 127 | |||
| 128 |
/// @notice The hook called before donate |
||
| 129 |
/// @param sender The initial msg.sender for the donate call |
||
| 130 |
/// @param key The key for the pool |
||
| 131 |
/// @param amount0 The amount of token0 being donated |
||
| 132 |
/// @param amount1 The amount of token1 being donated |
||
| 133 |
/// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook |
||
| 134 |
/// @return bytes4 The function selector for the hook |
||
| 135 |
function beforeDonate( |
||
| 136 |
address sender, |
||
| 137 |
PoolKey calldata key, |
||
| 138 |
uint256 amount0, |
||
| 139 |
uint256 amount1, |
||
| 140 |
bytes calldata hookData |
||
| 141 |
) external returns (bytes4); |
||
| 142 | |||
| 143 |
/// @notice The hook called after donate |
||
| 144 |
/// @param sender The initial msg.sender for the donate call |
||
| 145 |
/// @param key The key for the pool |
||
| 146 |
/// @param amount0 The amount of token0 being donated |
||
| 147 |
/// @param amount1 The amount of token1 being donated |
||
| 148 |
/// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook |
||
| 149 |
/// @return bytes4 The function selector for the hook |
||
| 150 |
function afterDonate( |
||
| 151 |
address sender, |
||
| 152 |
PoolKey calldata key, |
||
| 153 |
uint256 amount0, |
||
| 154 |
uint256 amount1, |
||
| 155 |
bytes calldata hookData |
||
| 156 |
) external returns (bytes4); |
||
| 157 |
} |
||
| 158 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 6 |
import {IHooks} from "./IHooks.sol";
|
||
| 7 |
import {IERC6909Claims} from "./external/IERC6909Claims.sol";
|
||
| 8 |
import {IProtocolFees} from "./IProtocolFees.sol";
|
||
| 9 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 10 |
import {PoolId} from "../types/PoolId.sol";
|
||
| 11 |
import {IExtsload} from "./IExtsload.sol";
|
||
| 12 |
import {IExttload} from "./IExttload.sol";
|
||
| 13 | |||
| 14 |
/// @notice Interface for the PoolManager |
||
| 15 |
interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload {
|
||
| 16 |
/// @notice Thrown when a currency is not netted out after the contract is unlocked |
||
| 17 |
error CurrencyNotSettled(); |
||
| 18 | |||
| 19 |
/// @notice Thrown when trying to interact with a non-initialized pool |
||
| 20 |
error PoolNotInitialized(); |
||
| 21 | |||
| 22 |
/// @notice Thrown when unlock is called, but the contract is already unlocked |
||
| 23 |
error AlreadyUnlocked(); |
||
| 24 | |||
| 25 |
/// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not |
||
| 26 |
error ManagerLocked(); |
||
| 27 | |||
| 28 |
/// @notice Pools are limited to type(int16).max tickSpacing in #initialize, to prevent overflow |
||
| 29 |
error TickSpacingTooLarge(int24 tickSpacing); |
||
| 30 | |||
| 31 |
/// @notice Pools must have a positive non-zero tickSpacing passed to #initialize |
||
| 32 |
error TickSpacingTooSmall(int24 tickSpacing); |
||
| 33 | |||
| 34 |
/// @notice PoolKey must have currencies where address(currency0) < address(currency1) |
||
| 35 |
error CurrenciesOutOfOrderOrEqual(address currency0, address currency1); |
||
| 36 | |||
| 37 |
/// @notice Thrown when a call to updateDynamicLPFee is made by an address that is not the hook, |
||
| 38 |
/// or on a pool that does not have a dynamic swap fee. |
||
| 39 |
error UnauthorizedDynamicLPFeeUpdate(); |
||
| 40 | |||
| 41 |
/// @notice Thrown when trying to swap amount of 0 |
||
| 42 |
error SwapAmountCannotBeZero(); |
||
| 43 | |||
| 44 |
///@notice Thrown when native currency is passed to a non native settlement |
||
| 45 |
error NonZeroNativeValue(); |
||
| 46 | |||
| 47 |
/// @notice Thrown when `clear` is called with an amount that is not exactly equal to the open currency delta. |
||
| 48 |
error MustClearExactPositiveDelta(); |
||
| 49 | |||
| 50 |
/// @notice Emitted when a new pool is initialized |
||
| 51 |
/// @param id The abi encoded hash of the pool key struct for the new pool |
||
| 52 |
/// @param currency0 The first currency of the pool by address sort order |
||
| 53 |
/// @param currency1 The second currency of the pool by address sort order |
||
| 54 |
/// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip |
||
| 55 |
/// @param tickSpacing The minimum number of ticks between initialized ticks |
||
| 56 |
/// @param hooks The hooks contract address for the pool, or address(0) if none |
||
| 57 |
event Initialize( |
||
| 58 |
PoolId indexed id, |
||
| 59 |
Currency indexed currency0, |
||
| 60 |
Currency indexed currency1, |
||
| 61 |
uint24 fee, |
||
| 62 |
int24 tickSpacing, |
||
| 63 |
IHooks hooks |
||
| 64 |
); |
||
| 65 | |||
| 66 |
/// @notice Emitted when a liquidity position is modified |
||
| 67 |
/// @param id The abi encoded hash of the pool key struct for the pool that was modified |
||
| 68 |
/// @param sender The address that modified the pool |
||
| 69 |
/// @param tickLower The lower tick of the position |
||
| 70 |
/// @param tickUpper The upper tick of the position |
||
| 71 |
/// @param liquidityDelta The amount of liquidity that was added or removed |
||
| 72 |
event ModifyLiquidity( |
||
| 73 |
PoolId indexed id, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta |
||
| 74 |
); |
||
| 75 | |||
| 76 |
/// @notice Emitted for swaps between currency0 and currency1 |
||
| 77 |
/// @param id The abi encoded hash of the pool key struct for the pool that was modified |
||
| 78 |
/// @param sender The address that initiated the swap call, and that received the callback |
||
| 79 |
/// @param amount0 The delta of the currency0 balance of the pool |
||
| 80 |
/// @param amount1 The delta of the currency1 balance of the pool |
||
| 81 |
/// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 |
||
| 82 |
/// @param liquidity The liquidity of the pool after the swap |
||
| 83 |
/// @param tick The log base 1.0001 of the price of the pool after the swap |
||
| 84 |
/// @param fee The swap fee in hundredths of a bip |
||
| 85 |
event Swap( |
||
| 86 |
PoolId indexed id, |
||
| 87 |
address indexed sender, |
||
| 88 |
int128 amount0, |
||
| 89 |
int128 amount1, |
||
| 90 |
uint160 sqrtPriceX96, |
||
| 91 |
uint128 liquidity, |
||
| 92 |
int24 tick, |
||
| 93 |
uint24 fee |
||
| 94 |
); |
||
| 95 | |||
| 96 |
/// @return int24 the constant representing the maximum tickSpacing for an initialized pool key |
||
| 97 |
function MAX_TICK_SPACING() external view returns (int24); |
||
| 98 | |||
| 99 |
/// @return int24 the constant representing the minimum tickSpacing for an initialized pool key |
||
| 100 |
function MIN_TICK_SPACING() external view returns (int24); |
||
| 101 | |||
| 102 |
/// @notice All interactions on the contract that account deltas require unlocking. A caller that calls `unlock` must implement |
||
| 103 |
/// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact with the remaining functions on this contract. |
||
| 104 |
/// @dev The only functions callable without an unlocking are `initialize` and `updateDynamicLPFee` |
||
| 105 |
/// @param data Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)` |
||
| 106 |
/// @return The data returned by the call to `IUnlockCallback(msg.sender).unlockCallback(data)` |
||
| 107 |
function unlock(bytes calldata data) external returns (bytes memory); |
||
| 108 | |||
| 109 |
/// @notice Initialize the state for a given pool ID |
||
| 110 |
/// @param key The pool key for the pool to initialize |
||
| 111 |
/// @param sqrtPriceX96 The initial square root price |
||
| 112 |
/// @param hookData The data to pass through to the initialize hooks |
||
| 113 |
/// @return tick The initial tick of the pool |
||
| 114 |
function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) |
||
| 115 |
external |
||
| 116 |
returns (int24 tick); |
||
| 117 | |||
| 118 |
struct ModifyLiquidityParams {
|
||
| 119 |
// the lower and upper tick of the position |
||
| 120 |
int24 tickLower; |
||
| 121 |
int24 tickUpper; |
||
| 122 |
// how to modify the liquidity |
||
| 123 |
int256 liquidityDelta; |
||
| 124 |
// a value to set if you want unique liquidity positions at the same range |
||
| 125 |
bytes32 salt; |
||
| 126 |
} |
||
| 127 | |||
| 128 |
/// @notice Modify the liquidity for the given pool |
||
| 129 |
/// @dev Poke by calling with a zero liquidityDelta |
||
| 130 |
/// @param key The pool to modify liquidity in |
||
| 131 |
/// @param params The parameters for modifying the liquidity |
||
| 132 |
/// @param hookData The data to pass through to the add/removeLiquidity hooks |
||
| 133 |
/// @return callerDelta The balance delta of the caller of modifyLiquidity. This is the total of both principal and fee deltas. |
||
| 134 |
/// @return feeDelta The balance delta of the fees generated in the liquidity range. Returned for informational purposes. |
||
| 135 |
function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData) |
||
| 136 |
external |
||
| 137 |
returns (BalanceDelta callerDelta, BalanceDelta feeDelta); |
||
| 138 | |||
| 139 |
struct SwapParams {
|
||
| 140 |
bool zeroForOne; |
||
| 141 |
int256 amountSpecified; |
||
| 142 |
uint160 sqrtPriceLimitX96; |
||
| 143 |
} |
||
| 144 | |||
| 145 |
/// @notice Swap against the given pool |
||
| 146 |
/// @param key The pool to swap in |
||
| 147 |
/// @param params The parameters for swapping |
||
| 148 |
/// @param hookData The data to pass through to the swap hooks |
||
| 149 |
/// @return swapDelta The balance delta of the address swapping |
||
| 150 |
/// @dev Swapping on low liquidity pools may cause unexpected swap amounts when liquidity available is less than amountSpecified. |
||
| 151 |
/// Additionally note that if interacting with hooks that have the BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG |
||
| 152 |
/// the hook may alter the swap input/output. Integrators should perform checks on the returned swapDelta. |
||
| 153 |
function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData) |
||
| 154 |
external |
||
| 155 |
returns (BalanceDelta swapDelta); |
||
| 156 | |||
| 157 |
/// @notice Donate the given currency amounts to the pool with the given pool key |
||
| 158 |
/// @param key The key of the pool to donate to |
||
| 159 |
/// @param amount0 The amount of currency0 to donate |
||
| 160 |
/// @param amount1 The amount of currency1 to donate |
||
| 161 |
/// @param hookData The data to pass through to the donate hooks |
||
| 162 |
/// @return BalanceDelta The delta of the caller after the donate |
||
| 163 |
function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) |
||
| 164 |
external |
||
| 165 |
returns (BalanceDelta); |
||
| 166 | |||
| 167 |
/// @notice Writes the current ERC20 balance of the specified currency to transient storage |
||
| 168 |
/// This is used to checkpoint balances for the manager and derive deltas for the caller. |
||
| 169 |
/// @dev This MUST be called before any ERC20 tokens are sent into the contract, but can be skipped |
||
| 170 |
/// for native tokens because the amount to settle is determined by the sent value. |
||
| 171 |
/// @param currency The currency whose balance to sync |
||
| 172 |
function sync(Currency currency) external; |
||
| 173 | |||
| 174 |
/// @notice Called by the user to net out some value owed to the user |
||
| 175 |
/// @dev Can also be used as a mechanism for _free_ flash loans |
||
| 176 |
/// @param currency The currency to withdraw from the pool manager |
||
| 177 |
/// @param to The address to withdraw to |
||
| 178 |
/// @param amount The amount of currency to withdraw |
||
| 179 |
function take(Currency currency, address to, uint256 amount) external; |
||
| 180 | |||
| 181 |
/// @notice Called by the user to pay what is owed |
||
| 182 |
/// @return paid The amount of currency settled |
||
| 183 |
function settle() external payable returns (uint256 paid); |
||
| 184 | |||
| 185 |
/// @notice Called by the user to pay on behalf of another address |
||
| 186 |
/// @param recipient The address to credit for the payment |
||
| 187 |
/// @return paid The amount of currency settled |
||
| 188 |
function settleFor(address recipient) external payable returns (uint256 paid); |
||
| 189 | |||
| 190 |
/// @notice WARNING - Any currency that is cleared, will be non-retreivable, and locked in the contract permanently. |
||
| 191 |
/// A call to clear will zero out a positive balance WITHOUT a corresponding transfer. |
||
| 192 |
/// @dev This could be used to clear a balance that is considered dust. |
||
| 193 |
/// Additionally, the amount must be the exact positive balance. This is to enforce that the caller is aware of the amount being cleared. |
||
| 194 |
function clear(Currency currency, uint256 amount) external; |
||
| 195 | |||
| 196 |
/// @notice Called by the user to move value into ERC6909 balance |
||
| 197 |
/// @param to The address to mint the tokens to |
||
| 198 |
/// @param id The currency address to mint to ERC6909s, as a uint256 |
||
| 199 |
/// @param amount The amount of currency to mint |
||
| 200 |
/// @dev The id is converted to a uint160 to correspond to a currency address |
||
| 201 |
/// If the upper 12 bytes are not 0, they will be 0-ed out |
||
| 202 |
function mint(address to, uint256 id, uint256 amount) external; |
||
| 203 | |||
| 204 |
/// @notice Called by the user to move value from ERC6909 balance |
||
| 205 |
/// @param from The address to burn the tokens from |
||
| 206 |
/// @param id The currency address to burn from ERC6909s, as a uint256 |
||
| 207 |
/// @param amount The amount of currency to burn |
||
| 208 |
/// @dev The id is converted to a uint160 to correspond to a currency address |
||
| 209 |
/// If the upper 12 bytes are not 0, they will be 0-ed out |
||
| 210 |
function burn(address from, uint256 id, uint256 amount) external; |
||
| 211 | |||
| 212 |
/// @notice Updates the pools lp fees for the a pool that has enabled dynamic lp fees. |
||
| 213 |
/// @param key The key of the pool to update dynamic LP fees for |
||
| 214 |
/// @param newDynamicLPFee The new dynamic pool LP fee |
||
| 215 |
function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external; |
||
| 216 |
} |
||
| 217 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 5 | |||
| 6 |
/// @notice Interface to fetch the protocol fees for a pool from the protocol fee controller |
||
| 7 |
interface IProtocolFeeController {
|
||
| 8 |
/// @notice Returns the protocol fees for a pool given the conditions of this contract |
||
| 9 |
/// @param poolKey The pool key to identify the pool. The controller may want to use attributes on the pool |
||
| 10 |
/// to determine the protocol fee, hence the entire key is needed. |
||
| 11 |
/// @return protocolFee The pool's protocol fee, expressed in hundredths of a bip. The upper 12 bits are for 1->0 |
||
| 12 |
/// and the lower 12 are for 0->1. The maximum is 1000 - meaning the maximum protocol fee is 0.1%. |
||
| 13 |
/// the protocolFee is taken from the input first, then the lpFee is taken from the remaining input |
||
| 14 |
function protocolFeeForPool(PoolKey memory poolKey) external view returns (uint24 protocolFee); |
||
| 15 |
} |
||
| 16 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.19; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IProtocolFeeController} from "../interfaces/IProtocolFeeController.sol";
|
||
| 6 |
import {PoolId} from "../types/PoolId.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 | |||
| 9 |
/// @notice Interface for all protocol-fee related functions in the pool manager |
||
| 10 |
interface IProtocolFees {
|
||
| 11 |
/// @notice Thrown when not enough gas is provided to look up the protocol fee |
||
| 12 |
error ProtocolFeeCannotBeFetched(); |
||
| 13 |
/// @notice Thrown when protocol fee is set too high |
||
| 14 |
error ProtocolFeeTooLarge(uint24 fee); |
||
| 15 | |||
| 16 |
/// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller. |
||
| 17 |
error InvalidCaller(); |
||
| 18 | |||
| 19 |
/// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController. |
||
| 20 |
event ProtocolFeeControllerUpdated(address indexed protocolFeeController); |
||
| 21 | |||
| 22 |
/// @notice Emitted when the protocol fee is updated for a pool. |
||
| 23 |
event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee); |
||
| 24 | |||
| 25 |
/// @notice Given a currency address, returns the protocol fees accrued in that currency |
||
| 26 |
/// @param currency The currency to check |
||
| 27 |
/// @return amount The amount of protocol fees accrued in the currency |
||
| 28 |
function protocolFeesAccrued(Currency currency) external view returns (uint256 amount); |
||
| 29 | |||
| 30 |
/// @notice Sets the protocol fee for the given pool |
||
| 31 |
/// @param key The key of the pool to set a protocol fee for |
||
| 32 |
/// @param newProtocolFee The fee to set |
||
| 33 |
function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external; |
||
| 34 | |||
| 35 |
/// @notice Sets the protocol fee controller |
||
| 36 |
/// @param controller The new protocol fee controller |
||
| 37 |
function setProtocolFeeController(IProtocolFeeController controller) external; |
||
| 38 | |||
| 39 |
/// @notice Collects the protocol fees for a given recipient and currency, returning the amount collected |
||
| 40 |
/// @param recipient The address to receive the protocol fees |
||
| 41 |
/// @param currency The currency to withdraw |
||
| 42 |
/// @param amount The amount of currency to withdraw |
||
| 43 |
/// @return amountCollected The amount of currency successfully withdrawn |
||
| 44 |
function collectProtocolFees(address recipient, Currency currency, uint256 amount) |
||
| 45 |
external |
||
| 46 |
returns (uint256 amountCollected); |
||
| 47 | |||
| 48 |
/// @notice Returns the current protocol fee controller address |
||
| 49 |
/// @return IProtocolFeeController The currency protocol fee controller |
||
| 50 |
function protocolFeeController() external view returns (IProtocolFeeController); |
||
| 51 |
} |
||
| 52 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @notice Interface for the callback executed when an address unlocks the pool manager |
||
| 5 |
interface IUnlockCallback {
|
||
| 6 |
/// @notice Called by the pool manager on `msg.sender` when the manager is unlocked |
||
| 7 |
/// @param data The data that was passed to the call to unlock |
||
| 8 |
/// @return Any data that you want to be returned from the unlock call |
||
| 9 |
function unlockCallback(bytes calldata data) external returns (bytes memory); |
||
| 10 |
} |
||
| 11 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title Minimal ERC20 interface for Uniswap |
||
| 5 |
/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 |
||
| 6 |
interface IERC20Minimal {
|
||
| 7 |
/// @notice Returns an account's balance in the token |
||
| 8 |
/// @param account The account for which to look up the number of tokens it has, i.e. its balance |
||
| 9 |
/// @return The number of tokens held by the account |
||
| 10 |
function balanceOf(address account) external view returns (uint256); |
||
| 11 | |||
| 12 |
/// @notice Transfers the amount of token from the `msg.sender` to the recipient |
||
| 13 |
/// @param recipient The account that will receive the amount transferred |
||
| 14 |
/// @param amount The number of tokens to send from the sender to the recipient |
||
| 15 |
/// @return Returns true for a successful transfer, false for an unsuccessful transfer |
||
| 16 |
function transfer(address recipient, uint256 amount) external returns (bool); |
||
| 17 | |||
| 18 |
/// @notice Returns the current allowance given to a spender by an owner |
||
| 19 |
/// @param owner The account of the token owner |
||
| 20 |
/// @param spender The account of the token spender |
||
| 21 |
/// @return The current allowance granted by `owner` to `spender` |
||
| 22 |
function allowance(address owner, address spender) external view returns (uint256); |
||
| 23 | |||
| 24 |
/// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` |
||
| 25 |
/// @param spender The account which will be allowed to spend a given amount of the owners tokens |
||
| 26 |
/// @param amount The amount of tokens allowed to be used by `spender` |
||
| 27 |
/// @return Returns true for a successful approval, false for unsuccessful |
||
| 28 |
function approve(address spender, uint256 amount) external returns (bool); |
||
| 29 | |||
| 30 |
/// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` |
||
| 31 |
/// @param sender The account from which the transfer will be initiated |
||
| 32 |
/// @param recipient The recipient of the transfer |
||
| 33 |
/// @param amount The amount of the transfer |
||
| 34 |
/// @return Returns true for a successful transfer, false for unsuccessful |
||
| 35 |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); |
||
| 36 | |||
| 37 |
/// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. |
||
| 38 |
/// @param from The account from which the tokens were sent, i.e. the balance decreased |
||
| 39 |
/// @param to The account to which the tokens were sent, i.e. the balance increased |
||
| 40 |
/// @param value The amount of tokens that were transferred |
||
| 41 |
event Transfer(address indexed from, address indexed to, uint256 value); |
||
| 42 | |||
| 43 |
/// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. |
||
| 44 |
/// @param owner The account that approved spending of its tokens |
||
| 45 |
/// @param spender The account for which the spending allowance was modified |
||
| 46 |
/// @param value The new allowance from the owner to the spender |
||
| 47 |
event Approval(address indexed owner, address indexed spender, uint256 value); |
||
| 48 |
} |
||
| 49 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @notice Interface for claims over a contract balance, wrapped as a ERC6909 |
||
| 5 |
interface IERC6909Claims {
|
||
| 6 |
/*////////////////////////////////////////////////////////////// |
||
| 7 |
EVENTS |
||
| 8 |
//////////////////////////////////////////////////////////////*/ |
||
| 9 | |||
| 10 |
event OperatorSet(address indexed owner, address indexed operator, bool approved); |
||
| 11 | |||
| 12 |
event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); |
||
| 13 | |||
| 14 |
event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount); |
||
| 15 | |||
| 16 |
/*////////////////////////////////////////////////////////////// |
||
| 17 |
FUNCTIONS |
||
| 18 |
//////////////////////////////////////////////////////////////*/ |
||
| 19 | |||
| 20 |
/// @notice Owner balance of an id. |
||
| 21 |
/// @param owner The address of the owner. |
||
| 22 |
/// @param id The id of the token. |
||
| 23 |
/// @return amount The balance of the token. |
||
| 24 |
function balanceOf(address owner, uint256 id) external view returns (uint256 amount); |
||
| 25 | |||
| 26 |
/// @notice Spender allowance of an id. |
||
| 27 |
/// @param owner The address of the owner. |
||
| 28 |
/// @param spender The address of the spender. |
||
| 29 |
/// @param id The id of the token. |
||
| 30 |
/// @return amount The allowance of the token. |
||
| 31 |
function allowance(address owner, address spender, uint256 id) external view returns (uint256 amount); |
||
| 32 | |||
| 33 |
/// @notice Checks if a spender is approved by an owner as an operator |
||
| 34 |
/// @param owner The address of the owner. |
||
| 35 |
/// @param spender The address of the spender. |
||
| 36 |
/// @return approved The approval status. |
||
| 37 |
function isOperator(address owner, address spender) external view returns (bool approved); |
||
| 38 | |||
| 39 |
/// @notice Transfers an amount of an id from the caller to a receiver. |
||
| 40 |
/// @param receiver The address of the receiver. |
||
| 41 |
/// @param id The id of the token. |
||
| 42 |
/// @param amount The amount of the token. |
||
| 43 |
/// @return bool True, always, unless the function reverts |
||
| 44 |
function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); |
||
| 45 | |||
| 46 |
/// @notice Transfers an amount of an id from a sender to a receiver. |
||
| 47 |
/// @param sender The address of the sender. |
||
| 48 |
/// @param receiver The address of the receiver. |
||
| 49 |
/// @param id The id of the token. |
||
| 50 |
/// @param amount The amount of the token. |
||
| 51 |
/// @return bool True, always, unless the function reverts |
||
| 52 |
function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool); |
||
| 53 | |||
| 54 |
/// @notice Approves an amount of an id to a spender. |
||
| 55 |
/// @param spender The address of the spender. |
||
| 56 |
/// @param id The id of the token. |
||
| 57 |
/// @param amount The amount of the token. |
||
| 58 |
/// @return bool True, always |
||
| 59 |
function approve(address spender, uint256 id, uint256 amount) external returns (bool); |
||
| 60 | |||
| 61 |
/// @notice Sets or removes an operator for the caller. |
||
| 62 |
/// @param operator The address of the operator. |
||
| 63 |
/// @param approved The approval status. |
||
| 64 |
/// @return bool True, always |
||
| 65 |
function setOperator(address operator, bool approved) external returns (bool); |
||
| 66 |
} |
||
| 67 |
| Lines covered: | 16 / 17 (94.1%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title BitMath |
||
| 5 |
/// @dev This library provides functionality for computing bit properties of an unsigned integer |
||
| 6 |
/// @author Solady (https://github.com/Vectorized/solady/blob/8200a70e8dc2a77ecb074fc2e99a2a0d36547522/src/utils/LibBit.sol) |
||
| 7 |
library BitMath {
|
||
| 8 |
/// @notice Returns the index of the most significant bit of the number, |
||
| 9 |
/// where the least significant bit is at index 0 and the most significant bit is at index 255 |
||
| 10 |
/// @param x the value for which to compute the most significant bit, must be greater than 0 |
||
| 11 |
/// @return r the index of the most significant bit |
||
| 12 |
√ 1
|
⟳ 2
|
function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
|
| 13 |
√ 2
|
⟳ 4
|
require(x > 0); |
| 14 | |||
| 15 |
assembly ("memory-safe") {
|
||
| 16 |
√ 5
|
⟳ 10
|
r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x))) |
| 17 |
√ 5
|
⟳ 10
|
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) |
| 18 |
√ 5
|
⟳ 10
|
r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) |
| 19 |
√ 5
|
⟳ 10
|
r := or(r, shl(4, lt(0xffff, shr(r, x)))) |
| 20 |
√ 5
|
⟳ 10
|
r := or(r, shl(3, lt(0xff, shr(r, x)))) |
| 21 |
// forgefmt: disable-next-item |
||
| 22 |
√ 5
|
⟳ 10
|
r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), |
| 23 |
√ 1
|
⟳ 2
|
0x0706060506020504060203020504030106050205030304010505030400000000)) |
| 24 |
} |
||
| 25 |
} |
||
| 26 | |||
| 27 |
/// @notice Returns the index of the least significant bit of the number, |
||
| 28 |
/// where the least significant bit is at index 0 and the most significant bit is at index 255 |
||
| 29 |
/// @param x the value for which to compute the least significant bit, must be greater than 0 |
||
| 30 |
/// @return r the index of the least significant bit |
||
| 31 |
√ 1
|
⟳ 2
|
function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {
|
| 32 |
√ 2
|
⟳ 4
|
require(x > 0); |
| 33 | |||
| 34 |
assembly ("memory-safe") {
|
||
| 35 |
// Isolate the least significant bit. |
||
| 36 |
√ 3
|
⟳ 6
|
x := and(x, add(not(x), 1)) |
| 37 |
// For the upper 3 bits of the result, use a De Bruijn-like lookup. |
||
| 38 |
// Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/ |
||
| 39 |
// forgefmt: disable-next-item |
||
| 40 |
r := shl(5, shr(252, shl(shl(2, shr(250, mul(x, |
||
| 41 |
√ 1
|
⟳ 2
|
0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))), |
| 42 |
√ 1
|
⟳ 2
|
0x8040405543005266443200005020610674053026020000107506200176117077))) |
| 43 |
// For the lower 5 bits of the result, use a De Bruijn lookup. |
||
| 44 |
// forgefmt: disable-next-item |
||
| 45 |
√ 5
|
⟳ 10
|
r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f), |
| 46 |
√ 1
|
⟳ 2
|
0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405)) |
| 47 |
} |
||
| 48 |
} |
||
| 49 |
} |
||
| 50 |
| Lines covered: | 8 / 9 (88.9%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 | |||
| 6 |
/// @title a library to store callers' currency deltas in transient storage |
||
| 7 |
/// @dev this library implements the equivalent of a mapping, as transient storage can only be accessed in assembly |
||
| 8 |
library CurrencyDelta {
|
||
| 9 |
/// @notice calculates which storage slot a delta should be stored in for a given account and currency |
||
| 10 |
function _computeSlot(address target, Currency currency) internal pure returns (bytes32 hashSlot) {
|
||
| 11 |
assembly ("memory-safe") {
|
||
| 12 |
√ 1
|
⟳ 1
|
mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff)) |
| 13 |
√ 5
|
⟳ 5
|
mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) |
| 14 |
√ 2
|
⟳ 2
|
hashSlot := keccak256(0, 64) |
| 15 |
} |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function getDelta(Currency currency, address target) internal view returns (int256 delta) {
|
||
| 19 |
bytes32 hashSlot = _computeSlot(target, currency); |
||
| 20 |
assembly {
|
||
| 21 |
√ 2
|
⟳ 2
|
delta := tload(hashSlot) |
| 22 |
} |
||
| 23 |
} |
||
| 24 | |||
| 25 |
/// @notice applies a new currency delta for a given account and currency |
||
| 26 |
/// @return previous The prior value |
||
| 27 |
/// @return next The modified result |
||
| 28 |
function applyDelta(Currency currency, address target, int128 delta) |
||
| 29 |
internal |
||
| 30 |
√ 2
|
⟳ 2
|
returns (int256 previous, int256 next) |
| 31 |
{
|
||
| 32 |
bytes32 hashSlot = _computeSlot(target, currency); |
||
| 33 | |||
| 34 |
assembly ("memory-safe") {
|
||
| 35 |
√ 4
|
⟳ 4
|
previous := tload(hashSlot) |
| 36 |
} |
||
| 37 |
√ 8
|
⟳ 8
|
next = previous + delta; |
| 38 |
assembly ("memory-safe") {
|
||
| 39 |
√ 2
|
⟳ 2
|
tstore(hashSlot, next) |
| 40 |
} |
||
| 41 |
} |
||
| 42 |
} |
||
| 43 |
| Lines covered: | 7 / 10 (70.0%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 6 | |||
| 7 |
library CurrencyReserves {
|
||
| 8 |
using CustomRevert for bytes4; |
||
| 9 | |||
| 10 |
/// @notice Thrown when a user has already synced a currency, but not yet settled |
||
| 11 |
error AlreadySynced(); |
||
| 12 | |||
| 13 |
/// bytes32(uint256(keccak256("ReservesOf")) - 1)
|
||
| 14 |
bytes32 constant RESERVES_OF_SLOT = 0x1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd95; |
||
| 15 |
/// bytes32(uint256(keccak256("Currency")) - 1)
|
||
| 16 |
bytes32 constant CURRENCY_SLOT = 0x27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b9; |
||
| 17 | |||
| 18 |
function requireNotSynced() internal view {
|
||
| 19 |
√ 3
|
⟳ 3
|
if (!getSyncedCurrency().isZero()) {
|
| 20 |
⟳ 1
|
AlreadySynced.selector.revertWith(); |
|
| 21 |
} |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function getSyncedCurrency() internal view returns (Currency currency) {
|
||
| 25 |
assembly {
|
||
| 26 |
√ 2
|
⟳ 2
|
currency := tload(CURRENCY_SLOT) |
| 27 |
} |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function resetCurrency() internal {
|
||
| 31 |
assembly {
|
||
| 32 |
√ 2
|
⟳ 2
|
tstore(CURRENCY_SLOT, 0) |
| 33 |
} |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function syncCurrencyAndReserves(Currency currency, uint256 value) internal {
|
||
| 37 |
assembly {
|
||
| 38 |
√ 3
|
⟳ 3
|
tstore(CURRENCY_SLOT, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) |
| 39 |
√ 2
|
⟳ 2
|
tstore(RESERVES_OF_SLOT, value) |
| 40 |
} |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function getSyncedReserves() internal view returns (uint256 value) {
|
||
| 44 |
assembly {
|
||
| 45 |
√ 1
|
⟳ 1
|
value := tload(RESERVES_OF_SLOT) |
| 46 |
} |
||
| 47 |
} |
||
| 48 |
} |
||
| 49 |
| Lines covered: | 26 / 34 (76.5%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title Library for reverting with custom errors efficiently |
||
| 5 |
/// @notice Contains functions for reverting with custom errors with different argument types efficiently |
||
| 6 |
/// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with |
||
| 7 |
/// `CustomError.selector.revertWith()` |
||
| 8 |
/// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately |
||
| 9 |
library CustomRevert {
|
||
| 10 |
/// @dev Reverts with the selector of a custom error in the scratch space |
||
| 11 |
function revertWith(bytes4 selector) internal pure {
|
||
| 12 |
assembly ("memory-safe") {
|
||
| 13 |
⟳ 2
|
mstore(0, selector) |
|
| 14 |
⟳ 2
|
revert(0, 0x04) |
|
| 15 |
} |
||
| 16 |
} |
||
| 17 | |||
| 18 |
/// @dev Reverts with a custom error with an address argument in the scratch space |
||
| 19 |
function revertWith(bytes4 selector, address addr) internal pure {
|
||
| 20 |
assembly ("memory-safe") {
|
||
| 21 |
⟳ 2
|
mstore(0, selector) |
|
| 22 |
⟳ 3
|
mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) |
|
| 23 |
⟳ 2
|
revert(0, 0x24) |
|
| 24 |
} |
||
| 25 |
} |
||
| 26 | |||
| 27 |
/// @dev Reverts with a custom error with an int24 argument in the scratch space |
||
| 28 |
function revertWith(bytes4 selector, int24 value) internal pure {
|
||
| 29 |
assembly ("memory-safe") {
|
||
| 30 |
⟳ 2
|
mstore(0, selector) |
|
| 31 |
⟳ 3
|
mstore(0x04, signextend(2, value)) |
|
| 32 |
⟳ 2
|
revert(0, 0x24) |
|
| 33 |
} |
||
| 34 |
} |
||
| 35 | |||
| 36 |
/// @dev Reverts with a custom error with a uint160 argument in the scratch space |
||
| 37 |
function revertWith(bytes4 selector, uint160 value) internal pure {
|
||
| 38 |
assembly ("memory-safe") {
|
||
| 39 |
mstore(0, selector) |
||
| 40 |
mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff)) |
||
| 41 |
revert(0, 0x24) |
||
| 42 |
} |
||
| 43 |
} |
||
| 44 | |||
| 45 |
/// @dev Reverts with a custom error with two int24 arguments |
||
| 46 |
function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure {
|
||
| 47 |
assembly ("memory-safe") {
|
||
| 48 |
⟳ 1
|
let fmp := mload(0x40) |
|
| 49 |
⟳ 2
|
mstore(fmp, selector) |
|
| 50 |
⟳ 4
|
mstore(add(fmp, 0x04), signextend(2, value1)) |
|
| 51 |
⟳ 4
|
mstore(add(fmp, 0x24), signextend(2, value2)) |
|
| 52 |
⟳ 2
|
revert(fmp, 0x44) |
|
| 53 |
} |
||
| 54 |
} |
||
| 55 | |||
| 56 |
/// @dev Reverts with a custom error with two uint160 arguments |
||
| 57 |
function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure {
|
||
| 58 |
assembly ("memory-safe") {
|
||
| 59 |
⟳ 1
|
let fmp := mload(0x40) |
|
| 60 |
⟳ 2
|
mstore(fmp, selector) |
|
| 61 |
⟳ 4
|
mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) |
|
| 62 |
⟳ 4
|
mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) |
|
| 63 |
⟳ 2
|
revert(fmp, 0x44) |
|
| 64 |
} |
||
| 65 |
} |
||
| 66 | |||
| 67 |
/// @dev Reverts with a custom error with two address arguments |
||
| 68 |
function revertWith(bytes4 selector, address value1, address value2) internal pure {
|
||
| 69 |
assembly ("memory-safe") {
|
||
| 70 |
mstore(0, selector) |
||
| 71 |
mstore(0x04, and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) |
||
| 72 |
mstore(0x24, and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) |
||
| 73 |
revert(0, 0x44) |
||
| 74 |
} |
||
| 75 |
} |
||
| 76 | |||
| 77 |
/// @notice bubble up the revert message returned by a call and revert with the selector provided |
||
| 78 |
/// @dev this function should only be used with custom errors of the type `CustomError(bytes revertReason)` |
||
| 79 |
function bubbleUpAndRevertWith(bytes4 selector) internal pure {
|
||
| 80 |
assembly ("memory-safe") {
|
||
| 81 |
⟳ 1
|
let size := returndatasize() |
|
| 82 |
⟳ 1
|
let fmp := mload(0x40) |
|
| 83 | |||
| 84 |
// Encode selector, offset, size, data |
||
| 85 |
⟳ 2
|
mstore(fmp, selector) |
|
| 86 |
⟳ 3
|
mstore(add(fmp, 0x04), 0x20) |
|
| 87 |
⟳ 3
|
mstore(add(fmp, 0x24), size) |
|
| 88 |
⟳ 4
|
returndatacopy(add(fmp, 0x44), 0, size) |
|
| 89 | |||
| 90 |
// Ensure the size is a multiple of 32 bytes |
||
| 91 |
⟳ 5
|
let encodedSize := add(0x44, mul(div(add(size, 31), 32), 32)) |
|
| 92 |
⟳ 2
|
revert(fmp, encodedSize) |
|
| 93 |
} |
||
| 94 |
} |
||
| 95 |
} |
||
| 96 |
| Lines covered: | 1 / 2 (50.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title FixedPoint128 |
||
| 5 |
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) |
||
| 6 |
library FixedPoint128 {
|
||
| 7 |
√ 399
|
⟳ 6
|
uint256 internal constant Q128 = 0x100000000000000000000000000000000; |
| 8 |
} |
||
| 9 |
| Lines covered: | 2 / 3 (66.7%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title FixedPoint96 |
||
| 5 |
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) |
||
| 6 |
/// @dev Used in SqrtPriceMath.sol |
||
| 7 |
library FixedPoint96 {
|
||
| 8 |
√ 4
|
⟳ 4
|
uint8 internal constant RESOLUTION = 96; |
| 9 |
√ 2
|
⟳ 2
|
uint256 internal constant Q96 = 0x1000000000000000000000000; |
| 10 |
} |
||
| 11 |
| Lines covered: | 29 / 30 (96.7%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title Contains 512-bit math functions |
||
| 5 |
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision |
||
| 6 |
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits |
||
| 7 |
library FullMath {
|
||
| 8 |
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 |
||
| 9 |
/// @param a The multiplicand |
||
| 10 |
/// @param b The multiplier |
||
| 11 |
/// @param denominator The divisor |
||
| 12 |
/// @return result The 256-bit result |
||
| 13 |
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv |
||
| 14 |
√ 8
|
⟳ 4
|
function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
|
| 15 |
unchecked {
|
||
| 16 |
// 512-bit multiply [prod1 prod0] = a * b |
||
| 17 |
// Compute the product mod 2**256 and mod 2**256 - 1 |
||
| 18 |
// then use the Chinese Remainder Theorem to reconstruct |
||
| 19 |
// the 512 bit result. The result is stored in two 256 |
||
| 20 |
// variables such that product = prod1 * 2**256 + prod0 |
||
| 21 |
√ 8
|
⟳ 4
|
uint256 prod0 = a * b; // Least significant 256 bits of the product |
| 22 |
uint256 prod1; // Most significant 256 bits of the product |
||
| 23 |
assembly ("memory-safe") {
|
||
| 24 |
√ 4
|
⟳ 2
|
let mm := mulmod(a, b, not(0)) |
| 25 |
√ 16
|
⟳ 8
|
prod1 := sub(sub(mm, prod0), lt(mm, prod0)) |
| 26 |
} |
||
| 27 | |||
| 28 |
// Make sure the result is less than 2**256. |
||
| 29 |
// Also prevents denominator == 0 |
||
| 30 |
√ 8
|
⟳ 4
|
require(denominator > prod1); |
| 31 | |||
| 32 |
// Handle non-overflow cases, 256 by 256 division |
||
| 33 |
√ 8
|
⟳ 4
|
if (prod1 == 0) {
|
| 34 |
assembly ("memory-safe") {
|
||
| 35 |
√ 16
|
⟳ 8
|
result := div(prod0, denominator) |
| 36 |
} |
||
| 37 |
√ 8
|
⟳ 4
|
return result; |
| 38 |
} |
||
| 39 | |||
| 40 |
/////////////////////////////////////////////// |
||
| 41 |
// 512 by 256 division. |
||
| 42 |
/////////////////////////////////////////////// |
||
| 43 | |||
| 44 |
// Make division exact by subtracting the remainder from [prod1 prod0] |
||
| 45 |
// Compute remainder using mulmod |
||
| 46 |
√ 1
|
⟳ 3467
|
uint256 remainder; |
| 47 |
assembly ("memory-safe") {
|
||
| 48 |
√ 3
|
⟳ 10401
|
remainder := mulmod(a, b, denominator) |
| 49 |
} |
||
| 50 |
// Subtract 256 bit number from 512 bit number |
||
| 51 |
assembly ("memory-safe") {
|
||
| 52 |
√ 3
|
⟳ 10401
|
prod1 := sub(prod1, gt(remainder, prod0)) |
| 53 |
√ 4
|
⟳ 13868
|
prod0 := sub(prod0, remainder) |
| 54 |
} |
||
| 55 | |||
| 56 |
// Factor powers of two out of denominator |
||
| 57 |
// Compute largest power of two divisor of denominator. |
||
| 58 |
// Always >= 1. |
||
| 59 |
√ 4
|
⟳ 13868
|
uint256 twos = (0 - denominator) & denominator; |
| 60 |
// Divide denominator by power of two |
||
| 61 |
assembly ("memory-safe") {
|
||
| 62 |
√ 5
|
⟳ 17335
|
denominator := div(denominator, twos) |
| 63 |
} |
||
| 64 | |||
| 65 |
// Divide [prod1 prod0] by the factors of two |
||
| 66 |
assembly ("memory-safe") {
|
||
| 67 |
√ 4
|
⟳ 13868
|
prod0 := div(prod0, twos) |
| 68 |
} |
||
| 69 |
// Shift in bits from prod1 into prod0. For this we need |
||
| 70 |
// to flip `twos` such that it is 2**256 / twos. |
||
| 71 |
// If twos is zero, then it becomes one |
||
| 72 |
assembly ("memory-safe") {
|
||
| 73 |
√ 5
|
⟳ 17335
|
twos := add(div(sub(0, twos), twos), 1) |
| 74 |
} |
||
| 75 |
√ 4
|
⟳ 13868
|
prod0 |= prod1 * twos; |
| 76 | |||
| 77 |
// Invert denominator mod 2**256 |
||
| 78 |
// Now that denominator is an odd number, it has an inverse |
||
| 79 |
// modulo 2**256 such that denominator * inv = 1 mod 2**256. |
||
| 80 |
// Compute the inverse by starting with a seed that is correct |
||
| 81 |
// correct for four bits. That is, denominator * inv = 1 mod 2**4 |
||
| 82 |
√ 2
|
⟳ 6934
|
uint256 inv = (3 * denominator) ^ 2; |
| 83 |
// Now use Newton-Raphson iteration to improve the precision. |
||
| 84 |
// Thanks to Hensel's lifting lemma, this also works in modular |
||
| 85 |
// arithmetic, doubling the correct bits in each step. |
||
| 86 |
√ 3
|
⟳ 10401
|
inv *= 2 - denominator * inv; // inverse mod 2**8 |
| 87 |
√ 3
|
⟳ 10401
|
inv *= 2 - denominator * inv; // inverse mod 2**16 |
| 88 |
√ 3
|
⟳ 10401
|
inv *= 2 - denominator * inv; // inverse mod 2**32 |
| 89 |
√ 3
|
⟳ 10401
|
inv *= 2 - denominator * inv; // inverse mod 2**64 |
| 90 |
√ 3
|
⟳ 10401
|
inv *= 2 - denominator * inv; // inverse mod 2**128 |
| 91 |
√ 3
|
⟳ 10401
|
inv *= 2 - denominator * inv; // inverse mod 2**256 |
| 92 | |||
| 93 |
// Because the division is now exact we can divide by multiplying |
||
| 94 |
// with the modular inverse of denominator. This will give us the |
||
| 95 |
// correct result modulo 2**256. Since the preconditions guarantee |
||
| 96 |
// that the outcome is less than 2**256, this is the final result. |
||
| 97 |
// We don't need to compute the high bits of the result and prod1 |
||
| 98 |
// is no longer required. |
||
| 99 |
√ 5
|
⟳ 17335
|
result = prod0 * inv; |
| 100 |
return result; |
||
| 101 |
} |
||
| 102 |
} |
||
| 103 | |||
| 104 |
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 |
||
| 105 |
/// @param a The multiplicand |
||
| 106 |
/// @param b The multiplier |
||
| 107 |
/// @param denominator The divisor |
||
| 108 |
/// @return result The 256-bit result |
||
| 109 |
√ 1
|
⟳ 1
|
function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
|
| 110 |
unchecked {
|
||
| 111 |
√ 4
|
⟳ 4
|
result = mulDiv(a, b, denominator); |
| 112 |
√ 3
|
⟳ 3
|
if (mulmod(a, b, denominator) != 0) {
|
| 113 |
√ 2
|
⟳ 2
|
require(++result > 0); |
| 114 |
} |
||
| 115 |
} |
||
| 116 |
} |
||
| 117 |
} |
||
| 118 |
| Lines covered: | 44 / 109 (40.4%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 5 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 6 |
import {SafeCast} from "./SafeCast.sol";
|
||
| 7 |
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
|
||
| 8 |
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 9 |
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
|
||
| 10 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 11 |
import {ParseBytes} from "./ParseBytes.sol";
|
||
| 12 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 13 | |||
| 14 |
/// @notice V4 decides whether to invoke specific hooks by inspecting the lowest significant bits of the address that |
||
| 15 |
/// the hooks contract is deployed to. |
||
| 16 |
/// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400 |
||
| 17 |
/// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used. |
||
| 18 |
library Hooks {
|
||
| 19 |
using LPFeeLibrary for uint24; |
||
| 20 |
using Hooks for IHooks; |
||
| 21 |
using SafeCast for int256; |
||
| 22 |
using BeforeSwapDeltaLibrary for BeforeSwapDelta; |
||
| 23 |
using ParseBytes for bytes; |
||
| 24 |
using CustomRevert for bytes4; |
||
| 25 | |||
| 26 |
uint160 internal constant ALL_HOOK_MASK = uint160((1 << 14) - 1); |
||
| 27 | |||
| 28 |
√ 1
|
⟳ 1
|
uint160 internal constant BEFORE_INITIALIZE_FLAG = 1 << 13; |
| 29 |
√ 1
|
⟳ 1
|
uint160 internal constant AFTER_INITIALIZE_FLAG = 1 << 12; |
| 30 | |||
| 31 |
√ 1
|
⟳ 1
|
uint160 internal constant BEFORE_ADD_LIQUIDITY_FLAG = 1 << 11; |
| 32 |
√ 2
|
⟳ 2
|
uint160 internal constant AFTER_ADD_LIQUIDITY_FLAG = 1 << 10; |
| 33 | |||
| 34 |
√ 1
|
⟳ 1
|
uint160 internal constant BEFORE_REMOVE_LIQUIDITY_FLAG = 1 << 9; |
| 35 |
√ 2
|
⟳ 1
|
uint160 internal constant AFTER_REMOVE_LIQUIDITY_FLAG = 1 << 8; |
| 36 | |||
| 37 |
√ 2
|
⟳ 2
|
uint160 internal constant BEFORE_SWAP_FLAG = 1 << 7; |
| 38 |
√ 2
|
⟳ 2
|
uint160 internal constant AFTER_SWAP_FLAG = 1 << 6; |
| 39 | |||
| 40 |
√ 1
|
⟳ 1
|
uint160 internal constant BEFORE_DONATE_FLAG = 1 << 5; |
| 41 |
√ 1
|
⟳ 1
|
uint160 internal constant AFTER_DONATE_FLAG = 1 << 4; |
| 42 | |||
| 43 |
√ 1
|
⟳ 1
|
uint160 internal constant BEFORE_SWAP_RETURNS_DELTA_FLAG = 1 << 3; |
| 44 |
√ 1
|
⟳ 1
|
uint160 internal constant AFTER_SWAP_RETURNS_DELTA_FLAG = 1 << 2; |
| 45 |
√ 1
|
⟳ 1
|
uint160 internal constant AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 1; |
| 46 |
√ 1
|
⟳ 1
|
uint160 internal constant AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 0; |
| 47 | |||
| 48 |
struct Permissions {
|
||
| 49 |
bool beforeInitialize; |
||
| 50 |
bool afterInitialize; |
||
| 51 |
bool beforeAddLiquidity; |
||
| 52 |
bool afterAddLiquidity; |
||
| 53 |
bool beforeRemoveLiquidity; |
||
| 54 |
bool afterRemoveLiquidity; |
||
| 55 |
bool beforeSwap; |
||
| 56 |
bool afterSwap; |
||
| 57 |
bool beforeDonate; |
||
| 58 |
bool afterDonate; |
||
| 59 |
bool beforeSwapReturnDelta; |
||
| 60 |
bool afterSwapReturnDelta; |
||
| 61 |
bool afterAddLiquidityReturnDelta; |
||
| 62 |
bool afterRemoveLiquidityReturnDelta; |
||
| 63 |
} |
||
| 64 | |||
| 65 |
/// @notice Thrown if the address will not lead to the specified hook calls being called |
||
| 66 |
/// @param hooks The address of the hooks contract |
||
| 67 |
error HookAddressNotValid(address hooks); |
||
| 68 | |||
| 69 |
/// @notice Hook did not return its selector |
||
| 70 |
error InvalidHookResponse(); |
||
| 71 | |||
| 72 |
/// @notice thrown when a hook call fails |
||
| 73 |
/// @param revertReason bubbled up revert reason |
||
| 74 |
error FailedHookCall(bytes revertReason); |
||
| 75 | |||
| 76 |
/// @notice The hook's delta changed the swap from exactIn to exactOut or vice versa |
||
| 77 |
error HookDeltaExceedsSwapAmount(); |
||
| 78 | |||
| 79 |
/// @notice Utility function intended to be used in hook constructors to ensure |
||
| 80 |
/// the deployed hooks address causes the intended hooks to be called |
||
| 81 |
/// @param permissions The hooks that are intended to be called |
||
| 82 |
/// @dev permissions param is memory as the function will be called from constructors |
||
| 83 |
function validateHookPermissions(IHooks self, Permissions memory permissions) internal pure {
|
||
| 84 |
if ( |
||
| 85 |
permissions.beforeInitialize != self.hasPermission(BEFORE_INITIALIZE_FLAG) |
||
| 86 |
|| permissions.afterInitialize != self.hasPermission(AFTER_INITIALIZE_FLAG) |
||
| 87 |
|| permissions.beforeAddLiquidity != self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG) |
||
| 88 |
|| permissions.afterAddLiquidity != self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) |
||
| 89 |
|| permissions.beforeRemoveLiquidity != self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG) |
||
| 90 |
|| permissions.afterRemoveLiquidity != self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG) |
||
| 91 |
|| permissions.beforeSwap != self.hasPermission(BEFORE_SWAP_FLAG) |
||
| 92 |
|| permissions.afterSwap != self.hasPermission(AFTER_SWAP_FLAG) |
||
| 93 |
|| permissions.beforeDonate != self.hasPermission(BEFORE_DONATE_FLAG) |
||
| 94 |
|| permissions.afterDonate != self.hasPermission(AFTER_DONATE_FLAG) |
||
| 95 |
|| permissions.beforeSwapReturnDelta != self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG) |
||
| 96 |
|| permissions.afterSwapReturnDelta != self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG) |
||
| 97 |
|| permissions.afterAddLiquidityReturnDelta != self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) |
||
| 98 |
|| permissions.afterRemoveLiquidityReturnDelta |
||
| 99 |
!= self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) |
||
| 100 |
) {
|
||
| 101 |
HookAddressNotValid.selector.revertWith(address(self)); |
||
| 102 |
} |
||
| 103 |
} |
||
| 104 | |||
| 105 |
/// @notice Ensures that the hook address includes at least one hook flag or dynamic fees, or is the 0 address |
||
| 106 |
/// @param self The hook to verify |
||
| 107 |
/// @param fee The fee of the pool the hook is used with |
||
| 108 |
/// @return bool True if the hook address is valid |
||
| 109 |
√ 1
|
⟳ 1
|
function isValidHookAddress(IHooks self, uint24 fee) internal pure returns (bool) {
|
| 110 |
// The hook can only have a flag to return a hook delta on an action if it also has the corresponding action flag |
||
| 111 |
√ 1
|
⟳ 1
|
if (!self.hasPermission(BEFORE_SWAP_FLAG) && self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) return false; |
| 112 |
√ 1
|
⟳ 1
|
if (!self.hasPermission(AFTER_SWAP_FLAG) && self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)) return false; |
| 113 |
√ 1
|
⟳ 1
|
if (!self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) && self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)) |
| 114 |
{
|
||
| 115 |
return false; |
||
| 116 |
} |
||
| 117 |
if ( |
||
| 118 |
!self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG) |
||
| 119 |
√ 1
|
⟳ 1
|
&& self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) |
| 120 |
) return false; |
||
| 121 | |||
| 122 |
// If there is no hook contract set, then fee cannot be dynamic |
||
| 123 |
// If a hook contract is set, it must have at least 1 flag set, or have a dynamic fee |
||
| 124 |
√ 4
|
⟳ 4
|
return address(self) == address(0) |
| 125 |
√ 2
|
⟳ 2
|
? !fee.isDynamicFee() |
| 126 |
: (uint160(address(self)) & ALL_HOOK_MASK > 0 || fee.isDynamicFee()); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
/// @notice performs a hook call using the given calldata on the given hook that doesnt return a delta |
||
| 130 |
/// @return result The complete data returned by the hook |
||
| 131 |
function callHook(IHooks self, bytes memory data) internal returns (bytes memory result) {
|
||
| 132 |
bool success; |
||
| 133 |
assembly ("memory-safe") {
|
||
| 134 |
success := call(gas(), self, 0, add(data, 0x20), mload(data), 0, 0) |
||
| 135 |
} |
||
| 136 |
// Revert with FailedHookCall, containing any error message to bubble up |
||
| 137 |
if (!success) FailedHookCall.selector.bubbleUpAndRevertWith(); |
||
| 138 | |||
| 139 |
// The call was successful, fetch the returned data |
||
| 140 |
assembly ("memory-safe") {
|
||
| 141 |
// allocate result byte array from the free memory pointer |
||
| 142 |
result := mload(0x40) |
||
| 143 |
// store new free memory pointer at the end of the array padded to 32 bytes |
||
| 144 |
mstore(0x40, add(result, and(add(returndatasize(), 0x3f), not(0x1f)))) |
||
| 145 |
// store length in memory |
||
| 146 |
mstore(result, returndatasize()) |
||
| 147 |
// copy return data to result |
||
| 148 |
returndatacopy(add(result, 0x20), 0, returndatasize()) |
||
| 149 |
} |
||
| 150 | |||
| 151 |
// Length must be at least 32 to contain the selector. Check expected selector and returned selector match. |
||
| 152 |
if (result.length < 32 || result.parseSelector() != data.parseSelector()) {
|
||
| 153 |
InvalidHookResponse.selector.revertWith(); |
||
| 154 |
} |
||
| 155 |
} |
||
| 156 | |||
| 157 |
/// @notice performs a hook call using the given calldata on the given hook |
||
| 158 |
/// @return int256 The delta returned by the hook |
||
| 159 |
function callHookWithReturnDelta(IHooks self, bytes memory data, bool parseReturn) internal returns (int256) {
|
||
| 160 |
bytes memory result = callHook(self, data); |
||
| 161 | |||
| 162 |
// If this hook wasnt meant to return something, default to 0 delta |
||
| 163 |
if (!parseReturn) return 0; |
||
| 164 | |||
| 165 |
// A length of 64 bytes is required to return a bytes4, and a 32 byte delta |
||
| 166 |
if (result.length != 64) InvalidHookResponse.selector.revertWith(); |
||
| 167 |
return result.parseReturnDelta(); |
||
| 168 |
} |
||
| 169 | |||
| 170 |
/// @notice modifier to prevent calling a hook if they initiated the action |
||
| 171 |
modifier noSelfCall(IHooks self) {
|
||
| 172 |
√ 5
|
⟳ 5
|
if (msg.sender != address(self)) {
|
| 173 |
_; |
||
| 174 |
} |
||
| 175 |
} |
||
| 176 | |||
| 177 |
/// @notice calls beforeInitialize hook if permissioned and validates return value |
||
| 178 |
function beforeInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) |
||
| 179 |
internal |
||
| 180 |
√ 1
|
⟳ 1
|
noSelfCall(self) |
| 181 |
{
|
||
| 182 |
if (self.hasPermission(BEFORE_INITIALIZE_FLAG)) {
|
||
| 183 |
self.callHook(abi.encodeCall(IHooks.beforeInitialize, (msg.sender, key, sqrtPriceX96, hookData))); |
||
| 184 |
} |
||
| 185 |
} |
||
| 186 | |||
| 187 |
/// @notice calls afterInitialize hook if permissioned and validates return value |
||
| 188 |
function afterInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, int24 tick, bytes calldata hookData) |
||
| 189 |
internal |
||
| 190 |
√ 1
|
⟳ 1
|
noSelfCall(self) |
| 191 |
{
|
||
| 192 |
if (self.hasPermission(AFTER_INITIALIZE_FLAG)) {
|
||
| 193 |
self.callHook(abi.encodeCall(IHooks.afterInitialize, (msg.sender, key, sqrtPriceX96, tick, hookData))); |
||
| 194 |
} |
||
| 195 |
} |
||
| 196 | |||
| 197 |
/// @notice calls beforeModifyLiquidity hook if permissioned and validates return value |
||
| 198 |
function beforeModifyLiquidity( |
||
| 199 |
IHooks self, |
||
| 200 |
PoolKey memory key, |
||
| 201 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 202 |
bytes calldata hookData |
||
| 203 |
√ 1
|
⟳ 1
|
) internal noSelfCall(self) {
|
| 204 |
√ 3
|
⟳ 3
|
if (params.liquidityDelta > 0 && self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) {
|
| 205 |
self.callHook(abi.encodeCall(IHooks.beforeAddLiquidity, (msg.sender, key, params, hookData))); |
||
| 206 |
√ 3
|
⟳ 3
|
} else if (params.liquidityDelta <= 0 && self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) {
|
| 207 |
self.callHook(abi.encodeCall(IHooks.beforeRemoveLiquidity, (msg.sender, key, params, hookData))); |
||
| 208 |
} |
||
| 209 |
} |
||
| 210 | |||
| 211 |
/// @notice calls afterModifyLiquidity hook if permissioned and validates return value |
||
| 212 |
function afterModifyLiquidity( |
||
| 213 |
IHooks self, |
||
| 214 |
PoolKey memory key, |
||
| 215 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 216 |
BalanceDelta delta, |
||
| 217 |
bytes calldata hookData |
||
| 218 |
√ 2
|
⟳ 2
|
) internal returns (BalanceDelta callerDelta, BalanceDelta hookDelta) {
|
| 219 |
√ 1
|
⟳ 1
|
if (msg.sender == address(self)) return (delta, BalanceDeltaLibrary.ZERO_DELTA); |
| 220 | |||
| 221 |
√ 1
|
⟳ 1
|
callerDelta = delta; |
| 222 |
√ 2
|
⟳ 2
|
if (params.liquidityDelta > 0) {
|
| 223 |
if (self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG)) {
|
||
| 224 |
hookDelta = BalanceDelta.wrap( |
||
| 225 |
self.callHookWithReturnDelta( |
||
| 226 |
abi.encodeCall(IHooks.afterAddLiquidity, (msg.sender, key, params, delta, hookData)), |
||
| 227 |
self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) |
||
| 228 |
) |
||
| 229 |
); |
||
| 230 |
callerDelta = callerDelta - hookDelta; |
||
| 231 |
} |
||
| 232 |
} else {
|
||
| 233 |
if (self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)) {
|
||
| 234 |
hookDelta = BalanceDelta.wrap( |
||
| 235 |
self.callHookWithReturnDelta( |
||
| 236 |
abi.encodeCall(IHooks.afterRemoveLiquidity, (msg.sender, key, params, delta, hookData)), |
||
| 237 |
self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) |
||
| 238 |
) |
||
| 239 |
); |
||
| 240 |
callerDelta = callerDelta - hookDelta; |
||
| 241 |
} |
||
| 242 |
} |
||
| 243 |
} |
||
| 244 | |||
| 245 |
/// @notice calls beforeSwap hook if permissioned and validates return value |
||
| 246 |
function beforeSwap(IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData) |
||
| 247 |
internal |
||
| 248 |
√ 2
|
⟳ 2
|
returns (int256 amountToSwap, BeforeSwapDelta hookReturn, uint24 lpFeeOverride) |
| 249 |
{
|
||
| 250 |
√ 4
|
⟳ 4
|
amountToSwap = params.amountSpecified; |
| 251 |
√ 1
|
⟳ 1
|
if (msg.sender == address(self)) return (amountToSwap, BeforeSwapDeltaLibrary.ZERO_DELTA, lpFeeOverride); |
| 252 | |||
| 253 |
if (self.hasPermission(BEFORE_SWAP_FLAG)) {
|
||
| 254 |
bytes memory result = callHook(self, abi.encodeCall(IHooks.beforeSwap, (msg.sender, key, params, hookData))); |
||
| 255 | |||
| 256 |
// A length of 96 bytes is required to return a bytes4, a 32 byte delta, and an LP fee |
||
| 257 |
if (result.length != 96) InvalidHookResponse.selector.revertWith(); |
||
| 258 | |||
| 259 |
// dynamic fee pools that do not want to override the cache fee, return 0 otherwise they return a valid fee with the override flag |
||
| 260 |
if (key.fee.isDynamicFee()) lpFeeOverride = result.parseFee(); |
||
| 261 | |||
| 262 |
// skip this logic for the case where the hook return is 0 |
||
| 263 |
if (self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) {
|
||
| 264 |
hookReturn = BeforeSwapDelta.wrap(result.parseReturnDelta()); |
||
| 265 | |||
| 266 |
// any return in unspecified is passed to the afterSwap hook for handling |
||
| 267 |
int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta(); |
||
| 268 | |||
| 269 |
// Update the swap amount according to the hook's return, and check that the swap type doesnt change (exact input/output) |
||
| 270 |
if (hookDeltaSpecified != 0) {
|
||
| 271 |
bool exactInput = amountToSwap < 0; |
||
| 272 |
amountToSwap += hookDeltaSpecified; |
||
| 273 |
if (exactInput ? amountToSwap > 0 : amountToSwap < 0) {
|
||
| 274 |
HookDeltaExceedsSwapAmount.selector.revertWith(); |
||
| 275 |
} |
||
| 276 |
} |
||
| 277 |
} |
||
| 278 |
} |
||
| 279 |
} |
||
| 280 | |||
| 281 |
/// @notice calls afterSwap hook if permissioned and validates return value |
||
| 282 |
function afterSwap( |
||
| 283 |
IHooks self, |
||
| 284 |
PoolKey memory key, |
||
| 285 |
IPoolManager.SwapParams memory params, |
||
| 286 |
BalanceDelta swapDelta, |
||
| 287 |
bytes calldata hookData, |
||
| 288 |
BeforeSwapDelta beforeSwapHookReturn |
||
| 289 |
√ 2
|
⟳ 2
|
) internal returns (BalanceDelta, BalanceDelta) {
|
| 290 |
√ 1
|
⟳ 1
|
if (msg.sender == address(self)) return (swapDelta, BalanceDeltaLibrary.ZERO_DELTA); |
| 291 | |||
| 292 |
√ 2
|
⟳ 2
|
int128 hookDeltaSpecified = beforeSwapHookReturn.getSpecifiedDelta(); |
| 293 |
√ 2
|
⟳ 2
|
int128 hookDeltaUnspecified = beforeSwapHookReturn.getUnspecifiedDelta(); |
| 294 | |||
| 295 |
if (self.hasPermission(AFTER_SWAP_FLAG)) {
|
||
| 296 |
hookDeltaUnspecified += self.callHookWithReturnDelta( |
||
| 297 |
abi.encodeCall(IHooks.afterSwap, (msg.sender, key, params, swapDelta, hookData)), |
||
| 298 |
self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG) |
||
| 299 |
).toInt128(); |
||
| 300 |
} |
||
| 301 | |||
| 302 |
√ 1
|
⟳ 1
|
BalanceDelta hookDelta; |
| 303 |
√ 4
|
⟳ 4
|
if (hookDeltaUnspecified != 0 || hookDeltaSpecified != 0) {
|
| 304 |
hookDelta = (params.amountSpecified < 0 == params.zeroForOne) |
||
| 305 |
? toBalanceDelta(hookDeltaSpecified, hookDeltaUnspecified) |
||
| 306 |
: toBalanceDelta(hookDeltaUnspecified, hookDeltaSpecified); |
||
| 307 | |||
| 308 |
// the caller has to pay for (or receive) the hook's delta |
||
| 309 |
swapDelta = swapDelta - hookDelta; |
||
| 310 |
} |
||
| 311 |
√ 3
|
⟳ 3
|
return (swapDelta, hookDelta); |
| 312 |
} |
||
| 313 | |||
| 314 |
/// @notice calls beforeDonate hook if permissioned and validates return value |
||
| 315 |
function beforeDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) |
||
| 316 |
internal |
||
| 317 |
√ 1
|
⟳ 1
|
noSelfCall(self) |
| 318 |
{
|
||
| 319 |
if (self.hasPermission(BEFORE_DONATE_FLAG)) {
|
||
| 320 |
self.callHook(abi.encodeCall(IHooks.beforeDonate, (msg.sender, key, amount0, amount1, hookData))); |
||
| 321 |
} |
||
| 322 |
} |
||
| 323 | |||
| 324 |
/// @notice calls afterDonate hook if permissioned and validates return value |
||
| 325 |
function afterDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) |
||
| 326 |
internal |
||
| 327 |
√ 1
|
⟳ 1
|
noSelfCall(self) |
| 328 |
{
|
||
| 329 |
if (self.hasPermission(AFTER_DONATE_FLAG)) {
|
||
| 330 |
self.callHook(abi.encodeCall(IHooks.afterDonate, (msg.sender, key, amount0, amount1, hookData))); |
||
| 331 |
} |
||
| 332 |
} |
||
| 333 | |||
| 334 |
function hasPermission(IHooks self, uint160 flag) internal pure returns (bool) {
|
||
| 335 |
√ 36
|
⟳ 34
|
return uint160(address(self)) & flag != 0; |
| 336 |
} |
||
| 337 |
} |
||
| 338 |
| Lines covered: | 10 / 15 (66.7%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 5 | |||
| 6 |
/// @notice Library of helper functions for a pools LP fee |
||
| 7 |
library LPFeeLibrary {
|
||
| 8 |
using LPFeeLibrary for uint24; |
||
| 9 |
using CustomRevert for bytes4; |
||
| 10 | |||
| 11 |
/// @notice Thrown when the static or dynamic fee on a pool exceeds 100%. |
||
| 12 |
error LPFeeTooLarge(uint24 fee); |
||
| 13 | |||
| 14 |
/// @notice An lp fee of exactly 0b1000000... signals a dynamic fee pool. This isnt a valid static fee as it is > MAX_LP_FEE |
||
| 15 |
√ 2
|
⟳ 3
|
uint24 public constant DYNAMIC_FEE_FLAG = 0x800000; |
| 16 | |||
| 17 |
/// @notice the second bit of the fee returned by beforeSwap is used to signal if the stored LP fee should be overridden in this swap |
||
| 18 |
// only dynamic-fee pools can return a fee via the beforeSwap hook |
||
| 19 |
√ 1
|
⟳ 1
|
uint24 public constant OVERRIDE_FEE_FLAG = 0x400000; |
| 20 | |||
| 21 |
/// @notice mask to remove the override fee flag from a fee returned by the beforeSwaphook |
||
| 22 |
uint24 public constant REMOVE_OVERRIDE_MASK = 0xBFFFFF; |
||
| 23 | |||
| 24 |
/// @notice the lp fee is represented in hundredths of a bip, so the max is 100% |
||
| 25 |
√ 2
|
⟳ 2
|
uint24 public constant MAX_LP_FEE = 1000000; |
| 26 | |||
| 27 |
/// @notice returns true if a pool's LP fee signals that the pool has a dynamic fee |
||
| 28 |
/// @param self The fee to check |
||
| 29 |
/// @return bool True of the fee is dynamic |
||
| 30 |
function isDynamicFee(uint24 self) internal pure returns (bool) {
|
||
| 31 |
√ 2
|
⟳ 3
|
return self == DYNAMIC_FEE_FLAG; |
| 32 |
} |
||
| 33 | |||
| 34 |
/// @notice returns true if an LP fee is valid, aka not above the maxmimum permitted fee |
||
| 35 |
/// @param self The fee to check |
||
| 36 |
/// @return bool True of the fee is valid |
||
| 37 |
function isValid(uint24 self) internal pure returns (bool) {
|
||
| 38 |
√ 2
|
⟳ 2
|
return self <= MAX_LP_FEE; |
| 39 |
} |
||
| 40 | |||
| 41 |
/// @notice validates whether an LP fee is larger than the maximum, and reverts if invalid |
||
| 42 |
/// @param self The fee to validate |
||
| 43 |
function validate(uint24 self) internal pure {
|
||
| 44 |
√ 3
|
⟳ 4
|
if (!self.isValid()) LPFeeTooLarge.selector.revertWith(self); |
| 45 |
} |
||
| 46 | |||
| 47 |
/// @notice gets and validates the initial LP fee for a pool. Dynamic fee pools have an initial fee of 0. |
||
| 48 |
/// @dev if a dynamic fee pool wants a non-0 initial fee, it should call `updateDynamicLPFee` in the afterInitialize hook |
||
| 49 |
/// @param self The fee to get the initial LP from |
||
| 50 |
/// @return initialFee 0 if the fee is dynamic, otherwise the fee (if valid) |
||
| 51 |
√ 1
|
⟳ 1
|
function getInitialLPFee(uint24 self) internal pure returns (uint24) {
|
| 52 |
// the initial fee for a dynamic fee pool is 0 |
||
| 53 |
√ 3
|
⟳ 3
|
if (self.isDynamicFee()) return 0; |
| 54 |
√ 1
|
⟳ 1
|
self.validate(); |
| 55 |
return self; |
||
| 56 |
} |
||
| 57 | |||
| 58 |
/// @notice returns true if the fee has the override flag set (2nd highest bit of the uint24) |
||
| 59 |
/// @param self The fee to check |
||
| 60 |
/// @return bool True of the fee has the override flag set |
||
| 61 |
function isOverride(uint24 self) internal pure returns (bool) {
|
||
| 62 |
√ 1
|
⟳ 1
|
return self & OVERRIDE_FEE_FLAG != 0; |
| 63 |
} |
||
| 64 | |||
| 65 |
/// @notice returns a fee with the override flag removed |
||
| 66 |
/// @param self The fee to remove the override flag from |
||
| 67 |
/// @return fee The fee without the override flag set |
||
| 68 |
function removeOverrideFlag(uint24 self) internal pure returns (uint24) {
|
||
| 69 |
return self & REMOVE_OVERRIDE_MASK; |
||
| 70 |
} |
||
| 71 | |||
| 72 |
/// @notice Removes the override flag and validates the fee (reverts if the fee is too large) |
||
| 73 |
/// @param self The fee to remove the override flag from, and then validate |
||
| 74 |
/// @return fee The fee without the override flag set (if valid) |
||
| 75 |
function removeOverrideFlagAndValidate(uint24 self) internal pure returns (uint24 fee) {
|
||
| 76 |
fee = self.removeOverrideFlag(); |
||
| 77 |
fee.validate(); |
||
| 78 |
} |
||
| 79 |
} |
||
| 80 |
| Lines covered: | 2 / 5 (40.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title Math library for liquidity |
||
| 5 |
library LiquidityMath {
|
||
| 6 |
/// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows |
||
| 7 |
/// @param x The liquidity before change |
||
| 8 |
/// @param y The delta by which liquidity should be changed |
||
| 9 |
/// @return z The liquidity delta |
||
| 10 |
function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) {
|
||
| 11 |
assembly ("memory-safe") {
|
||
| 12 |
√ 8
|
⟳ 8
|
z := add(and(x, 0xffffffffffffffffffffffffffffffff), signextend(15, y)) |
| 13 |
√ 4
|
⟳ 4
|
if shr(128, z) {
|
| 14 |
// revert SafeCastOverflow() |
||
| 15 |
mstore(0, 0x93dafdf1) |
||
| 16 |
revert(0x1c, 0x04) |
||
| 17 |
} |
||
| 18 |
} |
||
| 19 |
} |
||
| 20 |
} |
||
| 21 |
| Lines covered: | 3 / 5 (60.0%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
/// @notice This is a temporary library that allows us to use transient storage (tstore/tload) |
||
| 5 |
/// TODO: This library can be deleted when we have the transient keyword support in solidity. |
||
| 6 |
library Lock {
|
||
| 7 |
// The slot holding the unlocked state, transiently. bytes32(uint256(keccak256("Unlocked")) - 1)
|
||
| 8 |
bytes32 internal constant IS_UNLOCKED_SLOT = 0xc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab23; |
||
| 9 | |||
| 10 |
function unlock() internal {
|
||
| 11 |
assembly ("memory-safe") {
|
||
| 12 |
// unlock |
||
| 13 |
√ 2
|
⟳ 2
|
tstore(IS_UNLOCKED_SLOT, true) |
| 14 |
} |
||
| 15 |
} |
||
| 16 | |||
| 17 |
function lock() internal {
|
||
| 18 |
assembly ("memory-safe") {
|
||
| 19 |
√ 2
|
⟳ 2
|
tstore(IS_UNLOCKED_SLOT, false) |
| 20 |
} |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function isUnlocked() internal view returns (bool unlocked) {
|
||
| 24 |
assembly ("memory-safe") {
|
||
| 25 |
√ 10
|
⟳ 10
|
unlocked := tload(IS_UNLOCKED_SLOT) |
| 26 |
} |
||
| 27 |
} |
||
| 28 |
} |
||
| 29 |
| Lines covered: | 7 / 9 (77.8%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
/// @notice This is a temporary library that allows us to use transient storage (tstore/tload) |
||
| 5 |
/// for the nonzero delta count. |
||
| 6 |
/// TODO: This library can be deleted when we have the transient keyword support in solidity. |
||
| 7 |
library NonZeroDeltaCount {
|
||
| 8 |
// The slot holding the number of nonzero deltas. bytes32(uint256(keccak256("NonzeroDeltaCount")) - 1)
|
||
| 9 |
bytes32 internal constant NONZERO_DELTA_COUNT_SLOT = |
||
| 10 |
0x7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b; |
||
| 11 | |||
| 12 |
function read() internal view returns (uint256 count) {
|
||
| 13 |
assembly ("memory-safe") {
|
||
| 14 |
√ 1
|
⟳ 1
|
count := tload(NONZERO_DELTA_COUNT_SLOT) |
| 15 |
} |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function increment() internal {
|
||
| 19 |
assembly ("memory-safe") {
|
||
| 20 |
√ 1
|
⟳ 2
|
let count := tload(NONZERO_DELTA_COUNT_SLOT) |
| 21 |
√ 2
|
⟳ 4
|
count := add(count, 1) |
| 22 |
√ 2
|
⟳ 4
|
tstore(NONZERO_DELTA_COUNT_SLOT, count) |
| 23 |
} |
||
| 24 |
} |
||
| 25 | |||
| 26 |
/// @notice Potential to underflow. Ensure checks are performed by integrating contracts to ensure this does not happen. |
||
| 27 |
/// Current usage ensures this will not happen because we call decrement with known boundaries (only up to the number of times we call increment). |
||
| 28 |
function decrement() internal {
|
||
| 29 |
assembly ("memory-safe") {
|
||
| 30 |
√ 1
|
⟳ 1
|
let count := tload(NONZERO_DELTA_COUNT_SLOT) |
| 31 |
√ 2
|
⟳ 2
|
count := sub(count, 1) |
| 32 |
√ 2
|
⟳ 2
|
tstore(NONZERO_DELTA_COUNT_SLOT, count) |
| 33 |
} |
||
| 34 |
} |
||
| 35 |
} |
||
| 36 |
| Lines covered: | 0 / 4 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 | |||
| 3 |
pragma solidity ^0.8.0; |
||
| 4 | |||
| 5 |
/// @notice Parses bytes returned from hooks and the byte selector used to check return selectors from hooks. |
||
| 6 |
/// @dev parseSelector also is used to parse the expected selector |
||
| 7 |
/// For parsing hook returns, note that all hooks return either bytes4 or (bytes4, 32-byte-delta) or (bytes4, 32-byte-delta, uint24). |
||
| 8 |
library ParseBytes {
|
||
| 9 |
function parseSelector(bytes memory result) internal pure returns (bytes4 selector) {
|
||
| 10 |
// equivalent: (selector,) = abi.decode(result, (bytes4, int256)); |
||
| 11 |
assembly ("memory-safe") {
|
||
| 12 |
selector := mload(add(result, 0x20)) |
||
| 13 |
} |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function parseFee(bytes memory result) internal pure returns (uint24 lpFee) {
|
||
| 17 |
// equivalent: (,, lpFee) = abi.decode(result, (bytes4, int256, uint24)); |
||
| 18 |
assembly ("memory-safe") {
|
||
| 19 |
lpFee := mload(add(result, 0x60)) |
||
| 20 |
} |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function parseReturnDelta(bytes memory result) internal pure returns (int256 hookReturn) {
|
||
| 24 |
// equivalent: (, hookReturnDelta) = abi.decode(result, (bytes4, int256)); |
||
| 25 |
assembly ("memory-safe") {
|
||
| 26 |
hookReturn := mload(add(result, 0x40)) |
||
| 27 |
} |
||
| 28 |
} |
||
| 29 |
} |
||
| 30 |
| Lines covered: | 171 / 177 (96.6%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {SafeCast} from "./SafeCast.sol";
|
||
| 5 |
import {TickBitmap} from "./TickBitmap.sol";
|
||
| 6 |
import {Position} from "./Position.sol";
|
||
| 7 |
import {FullMath} from "./FullMath.sol";
|
||
| 8 |
import {FixedPoint128} from "./FixedPoint128.sol";
|
||
| 9 |
import {TickMath} from "./TickMath.sol";
|
||
| 10 |
import {SqrtPriceMath} from "./SqrtPriceMath.sol";
|
||
| 11 |
import {SwapMath} from "./SwapMath.sol";
|
||
| 12 |
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 13 |
import {Slot0} from "../types/Slot0.sol";
|
||
| 14 |
import {ProtocolFeeLibrary} from "./ProtocolFeeLibrary.sol";
|
||
| 15 |
import {LiquidityMath} from "./LiquidityMath.sol";
|
||
| 16 |
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
|
||
| 17 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 18 | |||
| 19 |
/// @notice a library with all actions that can be performed on a pool |
||
| 20 |
library Pool {
|
||
| 21 |
using SafeCast for *; |
||
| 22 |
using TickBitmap for mapping(int16 => uint256); |
||
| 23 |
using Position for mapping(bytes32 => Position.Info); |
||
| 24 |
using Position for Position.Info; |
||
| 25 |
using Pool for State; |
||
| 26 |
using ProtocolFeeLibrary for *; |
||
| 27 |
using LPFeeLibrary for uint24; |
||
| 28 |
using CustomRevert for bytes4; |
||
| 29 | |||
| 30 |
/// @notice Thrown when tickLower is not below tickUpper |
||
| 31 |
/// @param tickLower The invalid tickLower |
||
| 32 |
/// @param tickUpper The invalid tickUpper |
||
| 33 |
error TicksMisordered(int24 tickLower, int24 tickUpper); |
||
| 34 | |||
| 35 |
/// @notice Thrown when tickLower is less than min tick |
||
| 36 |
/// @param tickLower The invalid tickLower |
||
| 37 |
error TickLowerOutOfBounds(int24 tickLower); |
||
| 38 | |||
| 39 |
/// @notice Thrown when tickUpper exceeds max tick |
||
| 40 |
/// @param tickUpper The invalid tickUpper |
||
| 41 |
error TickUpperOutOfBounds(int24 tickUpper); |
||
| 42 | |||
| 43 |
/// @notice For the tick spacing, the tick has too much liquidity |
||
| 44 |
error TickLiquidityOverflow(int24 tick); |
||
| 45 | |||
| 46 |
/// @notice Thrown when trying to initialize an already initialized pool |
||
| 47 |
error PoolAlreadyInitialized(); |
||
| 48 | |||
| 49 |
/// @notice Thrown when trying to interact with a non-initialized pool |
||
| 50 |
error PoolNotInitialized(); |
||
| 51 | |||
| 52 |
/// @notice Thrown when sqrtPriceLimitX96 on a swap has already exceeded its limit |
||
| 53 |
/// @param sqrtPriceCurrentX96 The invalid, already surpassed sqrtPriceLimitX96 |
||
| 54 |
/// @param sqrtPriceLimitX96 The surpassed price limit |
||
| 55 |
error PriceLimitAlreadyExceeded(uint160 sqrtPriceCurrentX96, uint160 sqrtPriceLimitX96); |
||
| 56 | |||
| 57 |
/// @notice Thrown when sqrtPriceLimitX96 lies outside of valid tick/price range |
||
| 58 |
/// @param sqrtPriceLimitX96 The invalid, out-of-bounds sqrtPriceLimitX96 |
||
| 59 |
error PriceLimitOutOfBounds(uint160 sqrtPriceLimitX96); |
||
| 60 | |||
| 61 |
/// @notice Thrown by donate if there is currently 0 liquidity, since the fees will not go to any liquidity providers |
||
| 62 |
error NoLiquidityToReceiveFees(); |
||
| 63 | |||
| 64 |
/// @notice Thrown when trying to swap with max lp fee and specifying an output amount |
||
| 65 |
error InvalidFeeForExactOut(); |
||
| 66 | |||
| 67 |
// info stored for each initialized individual tick |
||
| 68 |
struct TickInfo {
|
||
| 69 |
// the total position liquidity that references this tick |
||
| 70 |
uint128 liquidityGross; |
||
| 71 |
// amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), |
||
| 72 |
int128 liquidityNet; |
||
| 73 |
// fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) |
||
| 74 |
// only has relative meaning, not absolute — the value depends on when the tick is initialized |
||
| 75 |
uint256 feeGrowthOutside0X128; |
||
| 76 |
uint256 feeGrowthOutside1X128; |
||
| 77 |
} |
||
| 78 | |||
| 79 |
/// @dev The state of a pool |
||
| 80 |
struct State {
|
||
| 81 |
Slot0 slot0; |
||
| 82 |
uint256 feeGrowthGlobal0X128; |
||
| 83 |
uint256 feeGrowthGlobal1X128; |
||
| 84 |
uint128 liquidity; |
||
| 85 |
mapping(int24 => TickInfo) ticks; |
||
| 86 |
mapping(int16 => uint256) tickBitmap; |
||
| 87 |
mapping(bytes32 => Position.Info) positions; |
||
| 88 |
} |
||
| 89 | |||
| 90 |
/// @dev Common checks for valid tick inputs. |
||
| 91 |
function checkTicks(int24 tickLower, int24 tickUpper) private pure {
|
||
| 92 |
√ 2
|
⟳ 5
|
if (tickLower >= tickUpper) TicksMisordered.selector.revertWith(tickLower, tickUpper); |
| 93 |
√ 5
|
⟳ 5
|
if (tickLower < TickMath.MIN_TICK) TickLowerOutOfBounds.selector.revertWith(tickLower); |
| 94 |
√ 5
|
⟳ 5
|
if (tickUpper > TickMath.MAX_TICK) TickUpperOutOfBounds.selector.revertWith(tickUpper); |
| 95 |
} |
||
| 96 | |||
| 97 |
function initialize(State storage self, uint160 sqrtPriceX96, uint24 protocolFee, uint24 lpFee) |
||
| 98 |
internal |
||
| 99 |
√ 2
|
⟳ 2
|
returns (int24 tick) |
| 100 |
{
|
||
| 101 |
√ 2
|
⟳ 3
|
if (self.slot0.sqrtPriceX96() != 0) PoolAlreadyInitialized.selector.revertWith(); |
| 102 | |||
| 103 |
√ 2
|
⟳ 2
|
tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); |
| 104 | |||
| 105 |
√ 3
|
⟳ 3
|
self.slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setProtocolFee(protocolFee) |
| 106 |
.setLpFee(lpFee); |
||
| 107 |
} |
||
| 108 | |||
| 109 |
function setProtocolFee(State storage self, uint24 protocolFee) internal {
|
||
| 110 |
√ 1
|
⟳ 1
|
self.checkPoolInitialized(); |
| 111 |
√ 2
|
⟳ 2
|
self.slot0 = self.slot0.setProtocolFee(protocolFee); |
| 112 |
} |
||
| 113 | |||
| 114 |
/// @notice Only dynamic fee pools may update the lp fee. |
||
| 115 |
function setLPFee(State storage self, uint24 lpFee) internal {
|
||
| 116 |
self.checkPoolInitialized(); |
||
| 117 |
self.slot0 = self.slot0.setLpFee(lpFee); |
||
| 118 |
} |
||
| 119 | |||
| 120 |
struct ModifyLiquidityParams {
|
||
| 121 |
// the address that owns the position |
||
| 122 |
address owner; |
||
| 123 |
// the lower and upper tick of the position |
||
| 124 |
int24 tickLower; |
||
| 125 |
int24 tickUpper; |
||
| 126 |
// any change in liquidity |
||
| 127 |
int128 liquidityDelta; |
||
| 128 |
// the spacing between ticks |
||
| 129 |
int24 tickSpacing; |
||
| 130 |
// used to distinguish positions of the same owner, at the same tick range |
||
| 131 |
bytes32 salt; |
||
| 132 |
} |
||
| 133 | |||
| 134 |
struct ModifyLiquidityState {
|
||
| 135 |
bool flippedLower; |
||
| 136 |
uint128 liquidityGrossAfterLower; |
||
| 137 |
bool flippedUpper; |
||
| 138 |
uint128 liquidityGrossAfterUpper; |
||
| 139 |
} |
||
| 140 | |||
| 141 |
/// @notice Effect changes to a position in a pool |
||
| 142 |
/// @dev PoolManager checks that the pool is initialized before calling |
||
| 143 |
/// @param params the position details and the change to the position's liquidity to effect |
||
| 144 |
/// @return delta the deltas of the token balances of the pool, from the liquidity change |
||
| 145 |
/// @return feeDelta the fees generated by the liquidity range |
||
| 146 |
function modifyLiquidity(State storage self, ModifyLiquidityParams memory params) |
||
| 147 |
internal |
||
| 148 |
√ 4
|
⟳ 4
|
returns (BalanceDelta delta, BalanceDelta feeDelta) |
| 149 |
{
|
||
| 150 |
√ 6
|
⟳ 6
|
int128 liquidityDelta = params.liquidityDelta; |
| 151 |
√ 5
|
⟳ 5
|
int24 tickLower = params.tickLower; |
| 152 |
√ 5
|
⟳ 5
|
int24 tickUpper = params.tickUpper; |
| 153 |
√ 1
|
⟳ 1
|
checkTicks(tickLower, tickUpper); |
| 154 | |||
| 155 |
{
|
||
| 156 |
ModifyLiquidityState memory state; |
||
| 157 | |||
| 158 |
// if we need to update the ticks, do it |
||
| 159 |
√ 2
|
⟳ 2
|
if (liquidityDelta != 0) {
|
| 160 |
√ 3
|
⟳ 3
|
(state.flippedLower, state.liquidityGrossAfterLower) = |
| 161 |
√ 5
|
⟳ 5
|
updateTick(self, tickLower, liquidityDelta, false); |
| 162 |
√ 11
|
⟳ 11
|
(state.flippedUpper, state.liquidityGrossAfterUpper) = updateTick(self, tickUpper, liquidityDelta, true); |
| 163 | |||
| 164 |
// `>` and `>=` are logically equivalent here but `>=` is cheaper |
||
| 165 |
√ 5
|
⟳ 5
|
if (liquidityDelta >= 0) {
|
| 166 |
√ 2
|
⟳ 2
|
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(params.tickSpacing); |
| 167 |
√ 2
|
⟳ 2
|
if (state.liquidityGrossAfterLower > maxLiquidityPerTick) {
|
| 168 |
⟳ 2
|
TickLiquidityOverflow.selector.revertWith(tickLower); |
|
| 169 |
} |
||
| 170 |
√ 2
|
⟳ 2
|
if (state.liquidityGrossAfterUpper > maxLiquidityPerTick) {
|
| 171 |
⟳ 2
|
TickLiquidityOverflow.selector.revertWith(tickUpper); |
|
| 172 |
} |
||
| 173 |
} |
||
| 174 | |||
| 175 |
√ 2
|
⟳ 2
|
if (state.flippedLower) {
|
| 176 |
√ 10
|
⟳ 10
|
self.tickBitmap.flipTick(tickLower, params.tickSpacing); |
| 177 |
} |
||
| 178 |
√ 1
|
⟳ 1
|
if (state.flippedUpper) {
|
| 179 |
√ 10
|
⟳ 10
|
self.tickBitmap.flipTick(tickUpper, params.tickSpacing); |
| 180 |
} |
||
| 181 |
} |
||
| 182 | |||
| 183 |
{
|
||
| 184 |
√ 2
|
⟳ 2
|
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = |
| 185 |
√ 4
|
⟳ 4
|
getFeeGrowthInside(self, tickLower, tickUpper); |
| 186 | |||
| 187 |
√ 10
|
⟳ 10
|
Position.Info storage position = self.positions.get(params.owner, tickLower, tickUpper, params.salt); |
| 188 |
(uint256 feesOwed0, uint256 feesOwed1) = |
||
| 189 |
√ 2
|
⟳ 2
|
position.update(liquidityDelta, feeGrowthInside0X128, feeGrowthInside1X128); |
| 190 | |||
| 191 |
// Fees earned from LPing are calculated, and returned |
||
| 192 |
√ 2
|
⟳ 2
|
feeDelta = toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128()); |
| 193 |
} |
||
| 194 | |||
| 195 |
// clear any tick data that is no longer needed |
||
| 196 |
√ 2
|
⟳ 2
|
if (liquidityDelta < 0) {
|
| 197 |
√ 2
|
if (state.flippedLower) {
|
|
| 198 |
√ 1
|
clearTick(self, tickLower); |
|
| 199 |
} |
||
| 200 |
√ 1
|
if (state.flippedUpper) {
|
|
| 201 |
√ 1
|
⟳ 1
|
clearTick(self, tickUpper); |
| 202 |
} |
||
| 203 |
} |
||
| 204 |
} |
||
| 205 | |||
| 206 |
√ 2
|
⟳ 2
|
if (liquidityDelta != 0) {
|
| 207 |
√ 5
|
⟳ 5
|
Slot0 _slot0 = self.slot0; |
| 208 |
√ 2
|
⟳ 2
|
(int24 tick, uint160 sqrtPriceX96) = (_slot0.tick(), _slot0.sqrtPriceX96()); |
| 209 |
√ 2
|
⟳ 2
|
if (tick < tickLower) {
|
| 210 |
// current tick is below the passed range; liquidity can only become in range by crossing from left to |
||
| 211 |
// right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it |
||
| 212 |
delta = toBalanceDelta( |
||
| 213 |
√ 1
|
⟳ 1
|
SqrtPriceMath.getAmount0Delta( |
| 214 |
√ 5
|
⟳ 5
|
TickMath.getSqrtPriceAtTick(tickLower), TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta |
| 215 |
).toInt128(), |
||
| 216 |
0 |
||
| 217 |
); |
||
| 218 |
√ 2
|
⟳ 2
|
} else if (tick < tickUpper) {
|
| 219 |
delta = toBalanceDelta( |
||
| 220 |
√ 3
|
⟳ 3
|
SqrtPriceMath.getAmount0Delta(sqrtPriceX96, TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta) |
| 221 |
.toInt128(), |
||
| 222 |
√ 5
|
⟳ 5
|
SqrtPriceMath.getAmount1Delta(TickMath.getSqrtPriceAtTick(tickLower), sqrtPriceX96, liquidityDelta) |
| 223 |
.toInt128() |
||
| 224 |
); |
||
| 225 | |||
| 226 |
√ 11
|
⟳ 11
|
self.liquidity = LiquidityMath.addDelta(self.liquidity, liquidityDelta); |
| 227 |
} else {
|
||
| 228 |
// current tick is above the passed range; liquidity can only become in range by crossing from right to |
||
| 229 |
// left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it |
||
| 230 |
delta = toBalanceDelta( |
||
| 231 |
√ 1
|
⟳ 1
|
0, |
| 232 |
√ 1
|
⟳ 1
|
SqrtPriceMath.getAmount1Delta( |
| 233 |
√ 5
|
⟳ 5
|
TickMath.getSqrtPriceAtTick(tickLower), TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta |
| 234 |
).toInt128() |
||
| 235 |
); |
||
| 236 |
} |
||
| 237 |
} |
||
| 238 |
} |
||
| 239 | |||
| 240 |
// the top level state of the swap, the results of which are recorded in storage at the end |
||
| 241 |
struct SwapState {
|
||
| 242 |
// the amount remaining to be swapped in/out of the input/output asset |
||
| 243 |
int256 amountSpecifiedRemaining; |
||
| 244 |
// the amount already swapped out/in of the output/input asset |
||
| 245 |
int256 amountCalculated; |
||
| 246 |
// current sqrt(price) |
||
| 247 |
uint160 sqrtPriceX96; |
||
| 248 |
// the tick associated with the current price |
||
| 249 |
int24 tick; |
||
| 250 |
// the global fee growth of the input token |
||
| 251 |
uint256 feeGrowthGlobalX128; |
||
| 252 |
// the current liquidity in range |
||
| 253 |
uint128 liquidity; |
||
| 254 |
} |
||
| 255 | |||
| 256 |
struct StepComputations {
|
||
| 257 |
// the price at the beginning of the step |
||
| 258 |
uint160 sqrtPriceStartX96; |
||
| 259 |
// the next tick to swap to from the current tick in the swap direction |
||
| 260 |
int24 tickNext; |
||
| 261 |
// whether tickNext is initialized or not |
||
| 262 |
bool initialized; |
||
| 263 |
// sqrt(price) for the next tick (1/0) |
||
| 264 |
uint160 sqrtPriceNextX96; |
||
| 265 |
// how much is being swapped in in this step |
||
| 266 |
uint256 amountIn; |
||
| 267 |
// how much is being swapped out |
||
| 268 |
uint256 amountOut; |
||
| 269 |
// how much fee is being paid in |
||
| 270 |
uint256 feeAmount; |
||
| 271 |
} |
||
| 272 | |||
| 273 |
struct SwapParams {
|
||
| 274 |
int24 tickSpacing; |
||
| 275 |
bool zeroForOne; |
||
| 276 |
int256 amountSpecified; |
||
| 277 |
uint160 sqrtPriceLimitX96; |
||
| 278 |
uint24 lpFeeOverride; |
||
| 279 |
} |
||
| 280 | |||
| 281 |
/// @notice Executes a swap against the state, and returns the amount deltas of the pool |
||
| 282 |
/// @dev PoolManager checks that the pool is initialized before calling |
||
| 283 |
function swap(State storage self, SwapParams memory params) |
||
| 284 |
internal |
||
| 285 |
√ 5
|
⟳ 5
|
returns (BalanceDelta result, uint256 feeForProtocol, uint24 swapFee, SwapState memory state) |
| 286 |
{
|
||
| 287 |
√ 3
|
⟳ 3
|
Slot0 slot0Start = self.slot0; |
| 288 |
√ 5
|
⟳ 5
|
bool zeroForOne = params.zeroForOne; |
| 289 | |||
| 290 |
√ 6
|
⟳ 6
|
uint128 liquidityStart = self.liquidity; |
| 291 |
uint256 protocolFee = |
||
| 292 |
√ 1
|
⟳ 1
|
zeroForOne ? slot0Start.protocolFee().getZeroForOneFee() : slot0Start.protocolFee().getOneForZeroFee(); |
| 293 | |||
| 294 |
√ 6
|
⟳ 6
|
state.amountSpecifiedRemaining = params.amountSpecified; |
| 295 |
√ 3
|
⟳ 3
|
state.amountCalculated = 0; |
| 296 |
√ 3
|
⟳ 3
|
state.sqrtPriceX96 = slot0Start.sqrtPriceX96(); |
| 297 |
√ 3
|
⟳ 3
|
state.tick = slot0Start.tick(); |
| 298 |
√ 7
|
⟳ 7
|
state.feeGrowthGlobalX128 = zeroForOne ? self.feeGrowthGlobal0X128 : self.feeGrowthGlobal1X128; |
| 299 |
√ 3
|
⟳ 3
|
state.liquidity = liquidityStart; |
| 300 | |||
| 301 |
// if the beforeSwap hook returned a valid fee override, use that as the LP fee, otherwise load from storage |
||
| 302 |
{
|
||
| 303 |
√ 3
|
⟳ 3
|
uint24 lpFee = params.lpFeeOverride.isOverride() |
| 304 |
? params.lpFeeOverride.removeOverrideFlagAndValidate() |
||
| 305 |
: slot0Start.lpFee(); |
||
| 306 | |||
| 307 |
√ 6
|
⟳ 6
|
swapFee = protocolFee == 0 ? lpFee : uint16(protocolFee).calculateSwapFee(lpFee); |
| 308 |
} |
||
| 309 | |||
| 310 |
√ 5
|
⟳ 5
|
bool exactInput = params.amountSpecified < 0; |
| 311 | |||
| 312 |
√ 5
|
⟳ 5
|
if (swapFee == LPFeeLibrary.MAX_LP_FEE && !exactInput) {
|
| 313 |
⟳ 1
|
InvalidFeeForExactOut.selector.revertWith(); |
|
| 314 |
} |
||
| 315 | |||
| 316 |
√ 2
|
⟳ 2
|
if (params.amountSpecified == 0) return (BalanceDeltaLibrary.ZERO_DELTA, 0, swapFee, state); |
| 317 | |||
| 318 |
√ 1
|
⟳ 1
|
if (zeroForOne) {
|
| 319 |
√ 4
|
⟳ 4
|
if (params.sqrtPriceLimitX96 >= slot0Start.sqrtPriceX96()) {
|
| 320 |
⟳ 7
|
PriceLimitAlreadyExceeded.selector.revertWith(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96); |
|
| 321 |
} |
||
| 322 |
√ 1
|
⟳ 1
|
if (params.sqrtPriceLimitX96 < TickMath.MIN_SQRT_PRICE) {
|
| 323 |
PriceLimitOutOfBounds.selector.revertWith(params.sqrtPriceLimitX96); |
||
| 324 |
} |
||
| 325 |
} else {
|
||
| 326 |
√ 4
|
⟳ 4
|
if (params.sqrtPriceLimitX96 <= slot0Start.sqrtPriceX96()) {
|
| 327 |
⟳ 1
|
PriceLimitAlreadyExceeded.selector.revertWith(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96); |
|
| 328 |
} |
||
| 329 |
√ 1
|
⟳ 1
|
if (params.sqrtPriceLimitX96 >= TickMath.MAX_SQRT_PRICE) {
|
| 330 |
PriceLimitOutOfBounds.selector.revertWith(params.sqrtPriceLimitX96); |
||
| 331 |
} |
||
| 332 |
} |
||
| 333 | |||
| 334 |
√ 396
|
⟳ 3
|
StepComputations memory step; |
| 335 | |||
| 336 |
// continue swapping as long as we haven't used the entire input/output and haven't reached the price limit |
||
| 337 |
√ 1582
|
⟳ 12
|
while (!(state.amountSpecifiedRemaining == 0 || state.sqrtPriceX96 == params.sqrtPriceLimitX96)) {
|
| 338 |
√ 1580
|
⟳ 12
|
step.sqrtPriceStartX96 = state.sqrtPriceX96; |
| 339 | |||
| 340 |
√ 2370
|
⟳ 18
|
(step.tickNext, step.initialized) = |
| 341 |
√ 4345
|
⟳ 33
|
self.tickBitmap.nextInitializedTickWithinOneWord(state.tick, params.tickSpacing, zeroForOne); |
| 342 | |||
| 343 |
// ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds |
||
| 344 |
if (step.tickNext <= TickMath.MIN_TICK) {
|
||
| 345 |
√ 3
|
⟳ 3
|
step.tickNext = TickMath.MIN_TICK; |
| 346 |
} |
||
| 347 |
√ 395
|
⟳ 3
|
if (step.tickNext >= TickMath.MAX_TICK) {
|
| 348 |
√ 3
|
⟳ 3
|
step.tickNext = TickMath.MAX_TICK; |
| 349 |
} |
||
| 350 | |||
| 351 |
// get the price for the next tick |
||
| 352 |
√ 2370
|
⟳ 18
|
step.sqrtPriceNextX96 = TickMath.getSqrtPriceAtTick(step.tickNext); |
| 353 | |||
| 354 |
// compute values to swap to the target tick, price limit, or point where input/output amount is exhausted |
||
| 355 |
√ 5135
|
⟳ 39
|
(state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep( |
| 356 |
√ 2370
|
⟳ 18
|
state.sqrtPriceX96, |
| 357 |
√ 1580
|
⟳ 12
|
SwapMath.getSqrtPriceTarget(zeroForOne, step.sqrtPriceNextX96, params.sqrtPriceLimitX96), |
| 358 |
√ 1580
|
⟳ 12
|
state.liquidity, |
| 359 |
√ 790
|
⟳ 6
|
state.amountSpecifiedRemaining, |
| 360 |
√ 395
|
⟳ 3
|
swapFee |
| 361 |
); |
||
| 362 | |||
| 363 |
√ 395
|
⟳ 3
|
if (!exactInput) {
|
| 364 |
unchecked {
|
||
| 365 |
√ 3467
|
⟳ 6934
|
state.amountSpecifiedRemaining -= step.amountOut.toInt256(); |
| 366 |
} |
||
| 367 |
√ 31203
|
⟳ 62406
|
state.amountCalculated -= (step.amountIn + step.feeAmount).toInt256(); |
| 368 |
} else {
|
||
| 369 |
// safe because we test that amountSpecified > amountIn + feeAmount in SwapMath |
||
| 370 |
unchecked {
|
||
| 371 |
√ 790
|
⟳ 6
|
state.amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256(); |
| 372 |
} |
||
| 373 |
√ 1975
|
⟳ 15
|
state.amountCalculated += step.amountOut.toInt256(); |
| 374 |
} |
||
| 375 | |||
| 376 |
// if the protocol fee is on, calculate how much is owed, decrement feeAmount, and increment protocolFee |
||
| 377 |
√ 790
|
⟳ 6
|
if (protocolFee > 0) {
|
| 378 |
unchecked {
|
||
| 379 |
// step.amountIn does not include the swap fee, as it's already been taken from it, |
||
| 380 |
// so add it back to get the total amountIn and use that to calculate the amount of fees owed to the protocol |
||
| 381 |
// this line cannot overflow due to limits on the size of protocolFee and params.amountSpecified |
||
| 382 |
√ 13868
|
⟳ 13868
|
uint256 delta = (step.amountIn + step.feeAmount) * protocolFee / ProtocolFeeLibrary.PIPS_DENOMINATOR; |
| 383 |
// subtract it from the total fee and add it to the protocol fee |
||
| 384 |
√ 10401
|
⟳ 10401
|
step.feeAmount -= delta; |
| 385 |
√ 17335
|
⟳ 17335
|
feeForProtocol += delta; |
| 386 |
} |
||
| 387 |
} |
||
| 388 | |||
| 389 |
// update global fee tracker |
||
| 390 |
√ 1580
|
⟳ 12
|
if (state.liquidity > 0) {
|
| 391 |
unchecked {
|
||
| 392 |
√ 2370
|
⟳ 9
|
state.feeGrowthGlobalX128 += FullMath.mulDiv(step.feeAmount, FixedPoint128.Q128, state.liquidity); |
| 393 |
} |
||
| 394 |
} |
||
| 395 | |||
| 396 |
// shift tick if we reached the next price |
||
| 397 |
√ 790
|
⟳ 4
|
if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
|
| 398 |
// if the tick is initialized, run the tick transition |
||
| 399 |
√ 394
|
⟳ 2
|
if (step.initialized) {
|
| 400 |
√ 3
|
⟳ 6
|
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = zeroForOne |
| 401 |
√ 2
|
⟳ 4
|
? (state.feeGrowthGlobalX128, self.feeGrowthGlobal1X128) |
| 402 |
√ 2
|
⟳ 4
|
: (self.feeGrowthGlobal0X128, state.feeGrowthGlobalX128); |
| 403 |
√ 1
|
⟳ 2
|
int128 liquidityNet = |
| 404 |
√ 4
|
⟳ 8
|
Pool.crossTick(self, step.tickNext, feeGrowthGlobal0X128, feeGrowthGlobal1X128); |
| 405 |
// if we're moving leftward, we interpret liquidityNet as the opposite sign |
||
| 406 |
// safe because liquidityNet cannot be type(int128).min |
||
| 407 |
unchecked {
|
||
| 408 |
√ 3
|
⟳ 6
|
if (zeroForOne) liquidityNet = -liquidityNet; |
| 409 |
} |
||
| 410 | |||
| 411 |
√ 6
|
⟳ 12
|
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); |
| 412 |
} |
||
| 413 | |||
| 414 |
// Equivalent to `state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;` |
||
| 415 |
unchecked {
|
||
| 416 |
// cannot cast a bool to an int24 in Solidity |
||
| 417 |
int24 _zeroForOne; |
||
| 418 |
assembly ("memory-safe") {
|
||
| 419 |
√ 394
|
⟳ 2
|
_zeroForOne := and(zeroForOne, 0xff) |
| 420 |
} |
||
| 421 |
√ 2758
|
⟳ 14
|
state.tick = step.tickNext - _zeroForOne; |
| 422 |
} |
||
| 423 |
√ 2
|
⟳ 2
|
} else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {
|
| 424 |
// recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved |
||
| 425 |
√ 5
|
⟳ 5
|
state.tick = TickMath.getTickAtSqrtPrice(state.sqrtPriceX96); |
| 426 |
} |
||
| 427 |
} |
||
| 428 | |||
| 429 |
√ 3
|
⟳ 3
|
self.slot0 = slot0Start.setTick(state.tick).setSqrtPriceX96(state.sqrtPriceX96); |
| 430 | |||
| 431 |
// update liquidity if it changed |
||
| 432 |
√ 11
|
⟳ 11
|
if (liquidityStart != state.liquidity) self.liquidity = state.liquidity; |
| 433 | |||
| 434 |
// update fee growth global |
||
| 435 |
√ 1
|
⟳ 1
|
if (!zeroForOne) {
|
| 436 |
√ 7
|
⟳ 7
|
self.feeGrowthGlobal1X128 = state.feeGrowthGlobalX128; |
| 437 |
} else {
|
||
| 438 |
√ 7
|
⟳ 7
|
self.feeGrowthGlobal0X128 = state.feeGrowthGlobalX128; |
| 439 |
} |
||
| 440 | |||
| 441 |
unchecked {
|
||
| 442 |
√ 2
|
⟳ 2
|
if (zeroForOne != exactInput) {
|
| 443 |
result = toBalanceDelta( |
||
| 444 |
√ 1
|
⟳ 1
|
state.amountCalculated.toInt128(), |
| 445 |
√ 2
|
⟳ 2
|
(params.amountSpecified - state.amountSpecifiedRemaining).toInt128() |
| 446 |
); |
||
| 447 |
} else {
|
||
| 448 |
result = toBalanceDelta( |
||
| 449 |
√ 2
|
⟳ 2
|
(params.amountSpecified - state.amountSpecifiedRemaining).toInt128(), |
| 450 |
√ 1
|
⟳ 1
|
state.amountCalculated.toInt128() |
| 451 |
); |
||
| 452 |
} |
||
| 453 |
} |
||
| 454 |
} |
||
| 455 | |||
| 456 |
/// @notice Donates the given amount of currency0 and currency1 to the pool |
||
| 457 |
√ 2
|
⟳ 2
|
function donate(State storage state, uint256 amount0, uint256 amount1) internal returns (BalanceDelta delta) {
|
| 458 |
√ 6
|
⟳ 6
|
uint128 liquidity = state.liquidity; |
| 459 |
√ 3
|
⟳ 4
|
if (liquidity == 0) NoLiquidityToReceiveFees.selector.revertWith(); |
| 460 |
unchecked {
|
||
| 461 |
// negation safe as amount0 and amount1 are always positive |
||
| 462 |
√ 2
|
⟳ 2
|
delta = toBalanceDelta(-(amount0.toInt128()), -(amount1.toInt128())); |
| 463 |
√ 2
|
⟳ 2
|
if (amount0 > 0) {
|
| 464 |
√ 6
|
⟳ 6
|
state.feeGrowthGlobal0X128 += FullMath.mulDiv(amount0, FixedPoint128.Q128, liquidity); |
| 465 |
} |
||
| 466 |
√ 2
|
⟳ 2
|
if (amount1 > 0) {
|
| 467 |
√ 6
|
⟳ 6
|
state.feeGrowthGlobal1X128 += FullMath.mulDiv(amount1, FixedPoint128.Q128, liquidity); |
| 468 |
} |
||
| 469 |
} |
||
| 470 |
} |
||
| 471 | |||
| 472 |
/// @notice Retrieves fee growth data |
||
| 473 |
/// @param self The Pool state struct |
||
| 474 |
/// @param tickLower The lower tick boundary of the position |
||
| 475 |
/// @param tickUpper The upper tick boundary of the position |
||
| 476 |
/// @return feeGrowthInside0X128 The all-time fee growth in token0, per unit of liquidity, inside the position's tick boundaries |
||
| 477 |
/// @return feeGrowthInside1X128 The all-time fee growth in token1, per unit of liquidity, inside the position's tick boundaries |
||
| 478 |
function getFeeGrowthInside(State storage self, int24 tickLower, int24 tickUpper) |
||
| 479 |
internal |
||
| 480 |
view |
||
| 481 |
√ 5
|
⟳ 5
|
returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) |
| 482 |
{
|
||
| 483 |
√ 3
|
⟳ 3
|
TickInfo storage lower = self.ticks[tickLower]; |
| 484 |
√ 10
|
⟳ 10
|
TickInfo storage upper = self.ticks[tickUpper]; |
| 485 |
√ 2
|
⟳ 2
|
int24 tickCurrent = self.slot0.tick(); |
| 486 | |||
| 487 |
unchecked {
|
||
| 488 |
√ 2
|
⟳ 2
|
if (tickCurrent < tickLower) {
|
| 489 |
√ 2
|
⟳ 2
|
feeGrowthInside0X128 = lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128; |
| 490 |
√ 2
|
⟳ 2
|
feeGrowthInside1X128 = lower.feeGrowthOutside1X128 - upper.feeGrowthOutside1X128; |
| 491 |
√ 2
|
⟳ 2
|
} else if (tickCurrent >= tickUpper) {
|
| 492 |
√ 2
|
⟳ 2
|
feeGrowthInside0X128 = upper.feeGrowthOutside0X128 - lower.feeGrowthOutside0X128; |
| 493 |
√ 2
|
⟳ 2
|
feeGrowthInside1X128 = upper.feeGrowthOutside1X128 - lower.feeGrowthOutside1X128; |
| 494 |
} else {
|
||
| 495 |
feeGrowthInside0X128 = |
||
| 496 |
√ 3
|
⟳ 3
|
self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128; |
| 497 |
feeGrowthInside1X128 = |
||
| 498 |
√ 3
|
⟳ 3
|
self.feeGrowthGlobal1X128 - lower.feeGrowthOutside1X128 - upper.feeGrowthOutside1X128; |
| 499 |
} |
||
| 500 |
} |
||
| 501 |
} |
||
| 502 | |||
| 503 |
/// @notice Updates a tick and returns true if the tick was flipped from initialized to uninitialized, or vice versa |
||
| 504 |
/// @param self The mapping containing all tick information for initialized ticks |
||
| 505 |
/// @param tick The tick that will be updated |
||
| 506 |
/// @param liquidityDelta A new amount of liquidity to be added (subtracted) when tick is crossed from left to right (right to left) |
||
| 507 |
/// @param upper true for updating a position's upper tick, or false for updating a position's lower tick |
||
| 508 |
/// @return flipped Whether the tick was flipped from initialized to uninitialized, or vice versa |
||
| 509 |
/// @return liquidityGrossAfter The total amount of liquidity for all positions that references the tick after the update |
||
| 510 |
function updateTick(State storage self, int24 tick, int128 liquidityDelta, bool upper) |
||
| 511 |
internal |
||
| 512 |
√ 6
|
⟳ 6
|
returns (bool flipped, uint128 liquidityGrossAfter) |
| 513 |
{
|
||
| 514 |
√ 6
|
⟳ 6
|
TickInfo storage info = self.ticks[tick]; |
| 515 | |||
| 516 |
uint128 liquidityGrossBefore; |
||
| 517 |
int128 liquidityNetBefore; |
||
| 518 |
assembly ("memory-safe") {
|
||
| 519 |
// load first slot of info which contains liquidityGross and liquidityNet packed |
||
| 520 |
// where the top 128 bits are liquidityNet and the bottom 128 bits are liquidityGross |
||
| 521 |
√ 4
|
⟳ 4
|
let liquidity := sload(info.slot) |
| 522 |
// slice off top 128 bits of liquidity (liquidityNet) to get just liquidityGross |
||
| 523 |
√ 2
|
⟳ 2
|
liquidityGrossBefore := shr(128, shl(128, liquidity)) |
| 524 |
// signed shift right 128 bits to get just liquidityNet |
||
| 525 |
√ 2
|
⟳ 2
|
liquidityNetBefore := sar(128, liquidity) |
| 526 |
} |
||
| 527 | |||
| 528 |
√ 4
|
⟳ 4
|
liquidityGrossAfter = LiquidityMath.addDelta(liquidityGrossBefore, liquidityDelta); |
| 529 | |||
| 530 |
√ 10
|
⟳ 10
|
flipped = (liquidityGrossAfter == 0) != (liquidityGrossBefore == 0); |
| 531 | |||
| 532 |
√ 2
|
⟳ 2
|
if (liquidityGrossBefore == 0) {
|
| 533 |
// by convention, we assume that all growth before a tick was initialized happened _below_ the tick |
||
| 534 |
√ 6
|
⟳ 6
|
if (tick <= self.slot0.tick()) {
|
| 535 |
√ 8
|
⟳ 8
|
info.feeGrowthOutside0X128 = self.feeGrowthGlobal0X128; |
| 536 |
√ 8
|
⟳ 8
|
info.feeGrowthOutside1X128 = self.feeGrowthGlobal1X128; |
| 537 |
} |
||
| 538 |
} |
||
| 539 | |||
| 540 |
// when the lower (upper) tick is crossed left to right (right to left), liquidity must be added (removed) |
||
| 541 |
√ 8
|
⟳ 8
|
int128 liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta; |
| 542 |
assembly ("memory-safe") {
|
||
| 543 |
// liquidityGrossAfter and liquidityNet are packed in the first slot of `info` |
||
| 544 |
// So we can store them with a single sstore by packing them ourselves first |
||
| 545 |
sstore( |
||
| 546 |
√ 2
|
⟳ 2
|
info.slot, |
| 547 |
// bitwise OR to pack liquidityGrossAfter and liquidityNet |
||
| 548 |
or( |
||
| 549 |
// liquidityGross is in the low bits, upper bits are already 0 |
||
| 550 |
√ 4
|
⟳ 4
|
and(liquidityGrossAfter, 0xffffffffffffffffffffffffffffffff), |
| 551 |
// shift liquidityNet to take the upper bits and lower bits get filled with 0 |
||
| 552 |
√ 4
|
⟳ 4
|
shl(128, liquidityNet) |
| 553 |
) |
||
| 554 |
) |
||
| 555 |
} |
||
| 556 |
} |
||
| 557 | |||
| 558 |
/// @notice Derives max liquidity per tick from given tick spacing |
||
| 559 |
/// @dev Executed within the pool constructor |
||
| 560 |
/// @param tickSpacing The amount of required tick separation, realized in multiples of `tickSpacing` |
||
| 561 |
/// e.g., a tickSpacing of 3 requires ticks to be initialized every 3rd tick i.e., ..., -6, -3, 0, 3, 6, ... |
||
| 562 |
/// @return result The max liquidity per tick |
||
| 563 |
function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128 result) {
|
||
| 564 |
// Equivalent to: |
||
| 565 |
// int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing; |
||
| 566 |
// int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing; |
||
| 567 |
// uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1; |
||
| 568 |
// return type(uint128).max / numTicks; |
||
| 569 |
int24 MAX_TICK = TickMath.MAX_TICK; |
||
| 570 |
int24 MIN_TICK = TickMath.MIN_TICK; |
||
| 571 |
// tick spacing will never be 0 since TickMath.MIN_TICK_SPACING is 1 |
||
| 572 |
assembly ("memory-safe") {
|
||
| 573 |
√ 1
|
⟳ 1
|
tickSpacing := signextend(2, tickSpacing) |
| 574 |
√ 3
|
⟳ 3
|
let minTick := mul(sdiv(MIN_TICK, tickSpacing), tickSpacing) |
| 575 |
√ 3
|
⟳ 3
|
let maxTick := mul(sdiv(MAX_TICK, tickSpacing), tickSpacing) |
| 576 |
√ 2
|
⟳ 2
|
let numTicks := add(sdiv(sub(maxTick, minTick), tickSpacing), 1) |
| 577 |
√ 1
|
⟳ 1
|
result := div(sub(shl(128, 1), 1), numTicks) |
| 578 |
} |
||
| 579 |
} |
||
| 580 | |||
| 581 |
/// @notice Reverts if the given pool has not been initialized |
||
| 582 |
function checkPoolInitialized(State storage self) internal view {
|
||
| 583 |
√ 3
|
⟳ 3
|
if (self.slot0.sqrtPriceX96() == 0) PoolNotInitialized.selector.revertWith(); |
| 584 |
} |
||
| 585 | |||
| 586 |
/// @notice Clears tick data |
||
| 587 |
/// @param self The mapping containing all initialized tick information for initialized ticks |
||
| 588 |
/// @param tick The tick that will be cleared |
||
| 589 |
function clearTick(State storage self, int24 tick) internal {
|
||
| 590 |
√ 6
|
delete self.ticks[tick]; |
|
| 591 |
} |
||
| 592 | |||
| 593 |
/// @notice Transitions to next tick as needed by price movement |
||
| 594 |
/// @param self The Pool state struct |
||
| 595 |
/// @param tick The destination tick of the transition |
||
| 596 |
/// @param feeGrowthGlobal0X128 The all-time global fee growth, per unit of liquidity, in token0 |
||
| 597 |
/// @param feeGrowthGlobal1X128 The all-time global fee growth, per unit of liquidity, in token1 |
||
| 598 |
/// @return liquidityNet The amount of liquidity added (subtracted) when tick is crossed from left to right (right to left) |
||
| 599 |
function crossTick(State storage self, int24 tick, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) |
||
| 600 |
internal |
||
| 601 |
√ 1
|
⟳ 2
|
returns (int128 liquidityNet) |
| 602 |
{
|
||
| 603 |
unchecked {
|
||
| 604 |
√ 4
|
⟳ 8
|
TickInfo storage info = self.ticks[tick]; |
| 605 |
√ 5
|
⟳ 10
|
info.feeGrowthOutside0X128 = feeGrowthGlobal0X128 - info.feeGrowthOutside0X128; |
| 606 |
√ 5
|
⟳ 10
|
info.feeGrowthOutside1X128 = feeGrowthGlobal1X128 - info.feeGrowthOutside1X128; |
| 607 |
√ 7
|
⟳ 14
|
liquidityNet = info.liquidityNet; |
| 608 |
} |
||
| 609 |
} |
||
| 610 |
} |
||
| 611 |
| Lines covered: | 19 / 20 (95.0%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {FullMath} from "./FullMath.sol";
|
||
| 5 |
import {FixedPoint128} from "./FixedPoint128.sol";
|
||
| 6 |
import {LiquidityMath} from "./LiquidityMath.sol";
|
||
| 7 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 8 | |||
| 9 |
/// @title Position |
||
| 10 |
/// @notice Positions represent an owner address' liquidity between a lower and upper tick boundary |
||
| 11 |
/// @dev Positions store additional state for tracking fees owed to the position |
||
| 12 |
library Position {
|
||
| 13 |
using CustomRevert for bytes4; |
||
| 14 | |||
| 15 |
/// @notice Cannot update a position with no liquidity |
||
| 16 |
error CannotUpdateEmptyPosition(); |
||
| 17 | |||
| 18 |
// info stored for each user's position |
||
| 19 |
struct Info {
|
||
| 20 |
// the amount of liquidity owned by this position |
||
| 21 |
uint128 liquidity; |
||
| 22 |
// fee growth per unit of liquidity as of the last update to liquidity or fees owed |
||
| 23 |
uint256 feeGrowthInside0LastX128; |
||
| 24 |
uint256 feeGrowthInside1LastX128; |
||
| 25 |
} |
||
| 26 | |||
| 27 |
/// @notice Returns the Info struct of a position, given an owner and position boundaries |
||
| 28 |
/// @param self The mapping containing all user positions |
||
| 29 |
/// @param owner The address of the position owner |
||
| 30 |
/// @param tickLower The lower tick boundary of the position |
||
| 31 |
/// @param tickUpper The upper tick boundary of the position |
||
| 32 |
/// @param salt A unique value to differentiate between multiple positions in the same range |
||
| 33 |
/// @return position The position info struct of the given owners' position |
||
| 34 |
function get(mapping(bytes32 => Info) storage self, address owner, int24 tickLower, int24 tickUpper, bytes32 salt) |
||
| 35 |
internal |
||
| 36 |
view |
||
| 37 |
returns (Info storage position) |
||
| 38 |
{
|
||
| 39 |
// positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)) |
||
| 40 |
bytes32 positionKey; |
||
| 41 | |||
| 42 |
assembly ("memory-safe") {
|
||
| 43 |
√ 1
|
⟳ 1
|
let fmp := mload(0x40) |
| 44 |
√ 1
|
⟳ 1
|
mstore(add(fmp, 0x26), salt) // [0x26, 0x46) |
| 45 |
√ 3
|
⟳ 3
|
mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26) |
| 46 |
√ 1
|
⟳ 1
|
mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23) |
| 47 |
√ 3
|
⟳ 3
|
mstore(fmp, owner) // [0x0c, 0x20) |
| 48 |
√ 2
|
⟳ 2
|
positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes |
| 49 | |||
| 50 |
// now clean the memory we used |
||
| 51 |
√ 3
|
⟳ 3
|
mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt |
| 52 |
√ 3
|
⟳ 3
|
mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt |
| 53 |
√ 4
|
⟳ 4
|
mstore(fmp, 0) // fmp held owner |
| 54 |
} |
||
| 55 |
√ 9
|
⟳ 9
|
position = self[positionKey]; |
| 56 |
} |
||
| 57 | |||
| 58 |
/// @notice Credits accumulated fees to a user's position |
||
| 59 |
/// @param self The individual position to update |
||
| 60 |
/// @param liquidityDelta The change in pool liquidity as a result of the position update |
||
| 61 |
/// @param feeGrowthInside0X128 The all-time fee growth in currency0, per unit of liquidity, inside the position's tick boundaries |
||
| 62 |
/// @param feeGrowthInside1X128 The all-time fee growth in currency1, per unit of liquidity, inside the position's tick boundaries |
||
| 63 |
/// @return feesOwed0 The amount of currency0 owed to the position owner |
||
| 64 |
/// @return feesOwed1 The amount of currency1 owed to the position owner |
||
| 65 |
function update( |
||
| 66 |
Info storage self, |
||
| 67 |
int128 liquidityDelta, |
||
| 68 |
uint256 feeGrowthInside0X128, |
||
| 69 |
uint256 feeGrowthInside1X128 |
||
| 70 |
√ 4
|
⟳ 4
|
) internal returns (uint256 feesOwed0, uint256 feesOwed1) {
|
| 71 |
√ 4
|
⟳ 4
|
uint128 liquidity = self.liquidity; |
| 72 | |||
| 73 |
√ 6
|
⟳ 6
|
if (liquidityDelta == 0) {
|
| 74 |
// disallow pokes for 0 liquidity positions |
||
| 75 |
√ 2
|
⟳ 3
|
if (liquidity == 0) CannotUpdateEmptyPosition.selector.revertWith(); |
| 76 |
} else {
|
||
| 77 |
√ 3
|
⟳ 3
|
self.liquidity = LiquidityMath.addDelta(liquidity, liquidityDelta); |
| 78 |
} |
||
| 79 | |||
| 80 |
// calculate accumulated fees. overflow in the subtraction of fee growth is expected |
||
| 81 |
unchecked {
|
||
| 82 |
feesOwed0 = |
||
| 83 |
√ 4
|
⟳ 4
|
FullMath.mulDiv(feeGrowthInside0X128 - self.feeGrowthInside0LastX128, liquidity, FixedPoint128.Q128); |
| 84 |
feesOwed1 = |
||
| 85 |
√ 4
|
⟳ 4
|
FullMath.mulDiv(feeGrowthInside1X128 - self.feeGrowthInside1LastX128, liquidity, FixedPoint128.Q128); |
| 86 |
} |
||
| 87 | |||
| 88 |
// update the position |
||
| 89 |
√ 3
|
⟳ 3
|
self.feeGrowthInside0LastX128 = feeGrowthInside0X128; |
| 90 |
√ 4
|
⟳ 4
|
self.feeGrowthInside1LastX128 = feeGrowthInside1X128; |
| 91 |
} |
||
| 92 |
} |
||
| 93 |
| Lines covered: | 10 / 13 (76.9%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @notice library of functions related to protocol fees |
||
| 5 |
library ProtocolFeeLibrary {
|
||
| 6 |
/// @notice Max protocol fee is 0.1% (1000 pips) |
||
| 7 |
/// @dev Increasing these values could lead to overflow in Pool.swap |
||
| 8 |
uint16 public constant MAX_PROTOCOL_FEE = 1000; |
||
| 9 | |||
| 10 |
/// @notice Thresholds used for optimized bounds checks on protocol fees |
||
| 11 |
uint24 internal constant FEE_0_THRESHOLD = 1001; |
||
| 12 |
uint24 internal constant FEE_1_THRESHOLD = 1001 << 12; |
||
| 13 | |||
| 14 |
/// @notice the protocol fee is represented in hundredths of a bip |
||
| 15 |
√ 3467
|
⟳ 3467
|
uint256 internal constant PIPS_DENOMINATOR = 1_000_000; |
| 16 | |||
| 17 |
function getZeroForOneFee(uint24 self) internal pure returns (uint16) {
|
||
| 18 |
√ 1
|
⟳ 1
|
return uint16(self & 0xfff); |
| 19 |
} |
||
| 20 | |||
| 21 |
function getOneForZeroFee(uint24 self) internal pure returns (uint16) {
|
||
| 22 |
√ 6
|
⟳ 6
|
return uint16(self >> 12); |
| 23 |
} |
||
| 24 | |||
| 25 |
function isValidProtocolFee(uint24 self) internal pure returns (bool valid) {
|
||
| 26 |
// Equivalent to: getZeroForOneFee(self) <= MAX_PROTOCOL_FEE && getOneForZeroFee(self) <= MAX_PROTOCOL_FEE |
||
| 27 |
assembly ("memory-safe") {
|
||
| 28 |
√ 4
|
⟳ 4
|
let isZeroForOneFeeOk := lt(and(self, 0xfff), FEE_0_THRESHOLD) |
| 29 |
√ 4
|
⟳ 4
|
let isOneForZeroFeeOk := lt(and(self, 0xfff000), FEE_1_THRESHOLD) |
| 30 |
√ 2
|
⟳ 2
|
valid := and(isZeroForOneFeeOk, isOneForZeroFeeOk) |
| 31 |
} |
||
| 32 |
} |
||
| 33 | |||
| 34 |
// The protocol fee is taken from the input amount first and then the LP fee is taken from the remaining |
||
| 35 |
// The swap fee is capped at 100% |
||
| 36 |
// Equivalent to protocolFee + lpFee(1_000_000 - protocolFee) / 1_000_000 |
||
| 37 |
/// @dev here `self` is just a single direction's protocol fee, not a packed type of 2 protocol fees |
||
| 38 |
function calculateSwapFee(uint16 self, uint24 lpFee) internal pure returns (uint24 swapFee) {
|
||
| 39 |
// protocolFee + lpFee - (protocolFee * lpFee / 1_000_000). Div rounds up to favor LPs over the protocol. |
||
| 40 |
assembly ("memory-safe") {
|
||
| 41 |
self := and(self, 0xffff) |
||
| 42 |
√ 1
|
⟳ 1
|
lpFee := and(lpFee, 0xffffff) |
| 43 |
√ 3
|
⟳ 3
|
let numerator := mul(self, lpFee) |
| 44 |
√ 4
|
⟳ 4
|
let divRoundingUp := add(div(numerator, PIPS_DENOMINATOR), gt(mod(numerator, PIPS_DENOMINATOR), 0)) |
| 45 |
√ 2
|
⟳ 2
|
swapFee := sub(add(self, lpFee), divRoundingUp) |
| 46 |
} |
||
| 47 |
} |
||
| 48 |
} |
||
| 49 |
| Lines covered: | 10 / 13 (76.9%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 5 | |||
| 6 |
/// @title Safe casting methods |
||
| 7 |
/// @notice Contains methods for safely casting between types |
||
| 8 |
library SafeCast {
|
||
| 9 |
using CustomRevert for bytes4; |
||
| 10 | |||
| 11 |
error SafeCastOverflow(); |
||
| 12 | |||
| 13 |
/// @notice Cast a uint256 to a uint160, revert on overflow |
||
| 14 |
/// @param x The uint256 to be downcasted |
||
| 15 |
/// @return y The downcasted integer, now type uint160 |
||
| 16 |
function toUint160(uint256 x) internal pure returns (uint160 y) {
|
||
| 17 |
√ 1
|
⟳ 1
|
y = uint160(x); |
| 18 |
√ 5
|
⟳ 5
|
if (y != x) SafeCastOverflow.selector.revertWith(); |
| 19 |
} |
||
| 20 | |||
| 21 |
/// @notice Cast a uint256 to a uint128, revert on overflow |
||
| 22 |
/// @param x The uint256 to be downcasted |
||
| 23 |
/// @return y The downcasted integer, now type uint128 |
||
| 24 |
function toUint128(uint256 x) internal pure returns (uint128 y) {
|
||
| 25 |
y = uint128(x); |
||
| 26 |
if (x != y) SafeCastOverflow.selector.revertWith(); |
||
| 27 |
} |
||
| 28 | |||
| 29 |
/// @notice Cast a int256 to a int128, revert on overflow or underflow |
||
| 30 |
/// @param x The int256 to be downcasted |
||
| 31 |
/// @return y The downcasted integer, now type int128 |
||
| 32 |
function toInt128(int256 x) internal pure returns (int128 y) {
|
||
| 33 |
√ 5
|
⟳ 5
|
y = int128(x); |
| 34 |
√ 30
|
⟳ 31
|
if (y != x) SafeCastOverflow.selector.revertWith(); |
| 35 |
} |
||
| 36 | |||
| 37 |
/// @notice Cast a uint256 to a int256, revert on overflow |
||
| 38 |
/// @param x The uint256 to be casted |
||
| 39 |
/// @return y The casted integer, now type int256 |
||
| 40 |
√ 2
|
⟳ 2
|
function toInt256(uint256 x) internal pure returns (int256 y) {
|
| 41 |
√ 2
|
⟳ 2
|
y = int256(x); |
| 42 |
√ 4
|
⟳ 4
|
if (y < 0) SafeCastOverflow.selector.revertWith(); |
| 43 |
} |
||
| 44 | |||
| 45 |
/// @notice Cast a uint256 to a int128, revert on overflow |
||
| 46 |
/// @param x The uint256 to be downcasted |
||
| 47 |
/// @return The downcasted integer, now type int128 |
||
| 48 |
√ 1
|
⟳ 1
|
function toInt128(uint256 x) internal pure returns (int128) {
|
| 49 |
√ 2
|
⟳ 3
|
if (x >= 1 << 127) SafeCastOverflow.selector.revertWith(); |
| 50 |
√ 1
|
⟳ 1
|
return int128(int256(x)); |
| 51 |
} |
||
| 52 |
} |
||
| 53 |
| Lines covered: | 59 / 73 (80.8%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {SafeCast} from "./SafeCast.sol";
|
||
| 5 | |||
| 6 |
import {FullMath} from "./FullMath.sol";
|
||
| 7 |
import {UnsafeMath} from "./UnsafeMath.sol";
|
||
| 8 |
import {FixedPoint96} from "./FixedPoint96.sol";
|
||
| 9 | |||
| 10 |
/// @title Functions based on Q64.96 sqrt price and liquidity |
||
| 11 |
/// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas |
||
| 12 |
library SqrtPriceMath {
|
||
| 13 |
using SafeCast for uint256; |
||
| 14 | |||
| 15 |
error InvalidPriceOrLiquidity(); |
||
| 16 |
error InvalidPrice(); |
||
| 17 |
error NotEnoughLiquidity(); |
||
| 18 |
error PriceOverflow(); |
||
| 19 | |||
| 20 |
/// @notice Gets the next sqrt price given a delta of currency0 |
||
| 21 |
/// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least |
||
| 22 |
/// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the |
||
| 23 |
/// price less in order to not send too much output. |
||
| 24 |
/// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96), |
||
| 25 |
/// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount). |
||
| 26 |
/// @param sqrtPX96 The starting price, i.e. before accounting for the currency0 delta |
||
| 27 |
/// @param liquidity The amount of usable liquidity |
||
| 28 |
/// @param amount How much of currency0 to add or remove from virtual reserves |
||
| 29 |
/// @param add Whether to add or remove the amount of currency0 |
||
| 30 |
/// @return The price after adding or removing amount, depending on add |
||
| 31 |
function getNextSqrtPriceFromAmount0RoundingUp(uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add) |
||
| 32 |
internal |
||
| 33 |
pure |
||
| 34 |
√ 1
|
⟳ 1
|
returns (uint160) |
| 35 |
{
|
||
| 36 |
// we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price |
||
| 37 |
√ 3
|
⟳ 3
|
if (amount == 0) return sqrtPX96; |
| 38 |
√ 5
|
⟳ 5
|
uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; |
| 39 | |||
| 40 |
if (add) {
|
||
| 41 |
unchecked {
|
||
| 42 |
√ 2
|
⟳ 2
|
uint256 product = amount * sqrtPX96; |
| 43 |
√ 4
|
⟳ 4
|
if (product / amount == sqrtPX96) {
|
| 44 |
√ 3
|
⟳ 3
|
uint256 denominator = numerator1 + product; |
| 45 |
√ 3
|
⟳ 3
|
if (denominator >= numerator1) {
|
| 46 |
// always fits in 160 bits |
||
| 47 |
√ 4
|
⟳ 4
|
return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator)); |
| 48 |
} |
||
| 49 |
} |
||
| 50 |
} |
||
| 51 |
// denominator is checked for overflow |
||
| 52 |
return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount)); |
||
| 53 |
} else {
|
||
| 54 |
unchecked {
|
||
| 55 |
√ 7
|
⟳ 7
|
uint256 product = amount * sqrtPX96; |
| 56 |
// if the product overflows, we know the denominator underflows |
||
| 57 |
// in addition, we must check that the denominator does not underflow |
||
| 58 |
// equivalent: if (product / amount != sqrtPX96 || numerator1 <= product) revert PriceOverflow(); |
||
| 59 |
assembly ("memory-safe") {
|
||
| 60 |
if iszero( |
||
| 61 |
and( |
||
| 62 |
√ 3
|
⟳ 3
|
eq(div(product, amount), and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)), |
| 63 |
√ 3
|
⟳ 3
|
gt(numerator1, product) |
| 64 |
) |
||
| 65 |
) {
|
||
| 66 |
mstore(0, 0xf5c787f1) // selector for PriceOverflow() |
||
| 67 |
revert(0x1c, 0x04) |
||
| 68 |
} |
||
| 69 |
} |
||
| 70 |
√ 1
|
⟳ 1
|
uint256 denominator = numerator1 - product; |
| 71 |
√ 1
|
⟳ 1
|
return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160(); |
| 72 |
} |
||
| 73 |
} |
||
| 74 |
} |
||
| 75 | |||
| 76 |
/// @notice Gets the next sqrt price given a delta of currency1 |
||
| 77 |
/// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least |
||
| 78 |
/// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the |
||
| 79 |
/// price less in order to not send too much output. |
||
| 80 |
/// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity |
||
| 81 |
/// @param sqrtPX96 The starting price, i.e., before accounting for the currency1 delta |
||
| 82 |
/// @param liquidity The amount of usable liquidity |
||
| 83 |
/// @param amount How much of currency1 to add, or remove, from virtual reserves |
||
| 84 |
/// @param add Whether to add, or remove, the amount of currency1 |
||
| 85 |
/// @return The price after adding or removing `amount` |
||
| 86 |
function getNextSqrtPriceFromAmount1RoundingDown(uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add) |
||
| 87 |
internal |
||
| 88 |
pure |
||
| 89 |
√ 1
|
⟳ 1
|
returns (uint160) |
| 90 |
{
|
||
| 91 |
// if we're adding (subtracting), rounding down requires rounding the quotient down (up) |
||
| 92 |
// in both cases, avoid a mulDiv for most inputs |
||
| 93 |
√ 1
|
⟳ 1
|
if (add) {
|
| 94 |
√ 1
|
⟳ 1
|
uint256 quotient = ( |
| 95 |
√ 1
|
⟳ 1
|
amount <= type(uint160).max |
| 96 |
√ 3
|
⟳ 3
|
? (amount << FixedPoint96.RESOLUTION) / liquidity |
| 97 |
: FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity) |
||
| 98 |
); |
||
| 99 | |||
| 100 |
√ 3
|
⟳ 3
|
return (uint256(sqrtPX96) + quotient).toUint160(); |
| 101 |
} else {
|
||
| 102 |
√ 1
|
⟳ 1
|
uint256 quotient = ( |
| 103 |
√ 1
|
⟳ 1
|
amount <= type(uint160).max |
| 104 |
√ 3
|
⟳ 3
|
? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity) |
| 105 |
: FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity) |
||
| 106 |
); |
||
| 107 | |||
| 108 |
// equivalent: if (sqrtPX96 <= quotient) revert NotEnoughLiquidity(); |
||
| 109 |
assembly ("memory-safe") {
|
||
| 110 |
√ 3
|
⟳ 3
|
if iszero(gt(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff), quotient)) {
|
| 111 |
mstore(0, 0x4323a555) // selector for NotEnoughLiquidity() |
||
| 112 |
revert(0x1c, 0x04) |
||
| 113 |
} |
||
| 114 |
} |
||
| 115 |
// always fits 160 bits |
||
| 116 |
unchecked {
|
||
| 117 |
√ 5
|
⟳ 5
|
return uint160(sqrtPX96 - quotient); |
| 118 |
} |
||
| 119 |
} |
||
| 120 |
} |
||
| 121 | |||
| 122 |
/// @notice Gets the next sqrt price given an input amount of currency0 or currency1 |
||
| 123 |
/// @dev Throws if price or liquidity are 0, or if the next price is out of bounds |
||
| 124 |
/// @param sqrtPX96 The starting price, i.e., before accounting for the input amount |
||
| 125 |
/// @param liquidity The amount of usable liquidity |
||
| 126 |
/// @param amountIn How much of currency0, or currency1, is being swapped in |
||
| 127 |
/// @param zeroForOne Whether the amount in is currency0 or currency1 |
||
| 128 |
/// @return uint160 The price after adding the input amount to currency0 or currency1 |
||
| 129 |
function getNextSqrtPriceFromInput(uint160 sqrtPX96, uint128 liquidity, uint256 amountIn, bool zeroForOne) |
||
| 130 |
internal |
||
| 131 |
pure |
||
| 132 |
√ 1
|
⟳ 1
|
returns (uint160) |
| 133 |
{
|
||
| 134 |
// equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity(); |
||
| 135 |
assembly ("memory-safe") {
|
||
| 136 |
if or( |
||
| 137 |
√ 2
|
⟳ 2
|
iszero(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)), |
| 138 |
√ 2
|
⟳ 2
|
iszero(and(liquidity, 0xffffffffffffffffffffffffffffffff)) |
| 139 |
) {
|
||
| 140 |
mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity() |
||
| 141 |
revert(0x1c, 0x04) |
||
| 142 |
} |
||
| 143 |
} |
||
| 144 | |||
| 145 |
// round to make sure that we don't pass the target price |
||
| 146 |
√ 1
|
⟳ 1
|
return zeroForOne |
| 147 |
√ 5
|
⟳ 5
|
? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true) |
| 148 |
√ 5
|
⟳ 5
|
: getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true); |
| 149 |
} |
||
| 150 | |||
| 151 |
/// @notice Gets the next sqrt price given an output amount of currency0 or currency1 |
||
| 152 |
/// @dev Throws if price or liquidity are 0 or the next price is out of bounds |
||
| 153 |
/// @param sqrtPX96 The starting price before accounting for the output amount |
||
| 154 |
/// @param liquidity The amount of usable liquidity |
||
| 155 |
/// @param amountOut How much of currency0, or currency1, is being swapped out |
||
| 156 |
/// @param zeroForOne Whether the amount out is currency1 or currency0 |
||
| 157 |
/// @return uint160 The price after removing the output amount of currency0 or currency1 |
||
| 158 |
function getNextSqrtPriceFromOutput(uint160 sqrtPX96, uint128 liquidity, uint256 amountOut, bool zeroForOne) |
||
| 159 |
internal |
||
| 160 |
pure |
||
| 161 |
√ 1
|
⟳ 1
|
returns (uint160) |
| 162 |
{
|
||
| 163 |
// equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity(); |
||
| 164 |
assembly ("memory-safe") {
|
||
| 165 |
if or( |
||
| 166 |
√ 2
|
⟳ 2
|
iszero(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)), |
| 167 |
√ 2
|
⟳ 2
|
iszero(and(liquidity, 0xffffffffffffffffffffffffffffffff)) |
| 168 |
) {
|
||
| 169 |
mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity() |
||
| 170 |
revert(0x1c, 0x04) |
||
| 171 |
} |
||
| 172 |
} |
||
| 173 | |||
| 174 |
// round to make sure that we pass the target price |
||
| 175 |
√ 1
|
⟳ 1
|
return zeroForOne |
| 176 |
√ 4
|
⟳ 4
|
? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false) |
| 177 |
√ 5
|
⟳ 5
|
: getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false); |
| 178 |
} |
||
| 179 | |||
| 180 |
/// @notice Gets the amount0 delta between two prices |
||
| 181 |
/// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), |
||
| 182 |
/// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower)) |
||
| 183 |
/// @param sqrtPriceAX96 A sqrt price |
||
| 184 |
/// @param sqrtPriceBX96 Another sqrt price |
||
| 185 |
/// @param liquidity The amount of usable liquidity |
||
| 186 |
/// @param roundUp Whether to round the amount up or down |
||
| 187 |
/// @return uint256 Amount of currency0 required to cover a position of size liquidity between the two passed prices |
||
| 188 |
function getAmount0Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity, bool roundUp) |
||
| 189 |
internal |
||
| 190 |
pure |
||
| 191 |
√ 1
|
⟳ 1
|
returns (uint256) |
| 192 |
{
|
||
| 193 |
unchecked {
|
||
| 194 |
√ 2
|
⟳ 2
|
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
| 195 | |||
| 196 |
// equivalent: if (sqrtPriceAX96 == 0) revert InvalidPrice(); |
||
| 197 |
assembly ("memory-safe") {
|
||
| 198 |
√ 2
|
⟳ 2
|
if iszero(and(sqrtPriceAX96, 0xffffffffffffffffffffffffffffffffffffffff)) {
|
| 199 |
mstore(0, 0x00bfc921) // selector for InvalidPrice() |
||
| 200 |
revert(0x1c, 0x04) |
||
| 201 |
} |
||
| 202 |
} |
||
| 203 | |||
| 204 |
√ 5
|
⟳ 5
|
uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; |
| 205 |
√ 3
|
⟳ 3
|
uint256 numerator2 = sqrtPriceBX96 - sqrtPriceAX96; |
| 206 | |||
| 207 |
√ 1
|
⟳ 1
|
return roundUp |
| 208 |
√ 5
|
⟳ 5
|
? UnsafeMath.divRoundingUp(FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtPriceBX96), sqrtPriceAX96) |
| 209 |
√ 1975
|
⟳ 34670
|
: FullMath.mulDiv(numerator1, numerator2, sqrtPriceBX96) / sqrtPriceAX96; |
| 210 |
} |
||
| 211 |
} |
||
| 212 | |||
| 213 |
/// @notice Equivalent to: `a >= b ? a - b : b - a` |
||
| 214 |
function absDiff(uint160 a, uint160 b) internal pure returns (uint256 res) {
|
||
| 215 |
assembly ("memory-safe") {
|
||
| 216 |
let diff := |
||
| 217 |
√ 4
|
⟳ 4
|
sub(and(a, 0xffffffffffffffffffffffffffffffffffffffff), and(b, 0xffffffffffffffffffffffffffffffffffffffff)) |
| 218 |
// mask = 0 if a >= b else -1 (all 1s) |
||
| 219 |
√ 1
|
⟳ 1
|
let mask := sar(255, diff) |
| 220 |
// if a >= b, res = a - b = 0 ^ (a - b) |
||
| 221 |
// if a < b, res = b - a = ~~(b - a) = ~(-(b - a) - 1) = ~(a - b - 1) = (-1) ^ (a - b - 1) |
||
| 222 |
// either way, res = mask ^ (a - b + mask) |
||
| 223 |
√ 3
|
⟳ 3
|
res := xor(mask, add(mask, diff)) |
| 224 |
} |
||
| 225 |
} |
||
| 226 | |||
| 227 |
/// @notice Gets the amount1 delta between two prices |
||
| 228 |
/// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower)) |
||
| 229 |
/// @param sqrtPriceAX96 A sqrt price |
||
| 230 |
/// @param sqrtPriceBX96 Another sqrt price |
||
| 231 |
/// @param liquidity The amount of usable liquidity |
||
| 232 |
/// @param roundUp Whether to round the amount up, or down |
||
| 233 |
/// @return amount1 Amount of currency1 required to cover a position of size liquidity between the two passed prices |
||
| 234 |
function getAmount1Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity, bool roundUp) |
||
| 235 |
internal |
||
| 236 |
pure |
||
| 237 |
√ 1
|
⟳ 1
|
returns (uint256 amount1) |
| 238 |
{
|
||
| 239 |
uint256 numerator = absDiff(sqrtPriceAX96, sqrtPriceBX96); |
||
| 240 |
uint256 denominator = FixedPoint96.Q96; |
||
| 241 |
uint256 _liquidity; |
||
| 242 |
assembly ("memory-safe") {
|
||
| 243 |
// avoid implicit upcasting |
||
| 244 |
√ 1
|
⟳ 1
|
_liquidity := and(liquidity, 0xffffffffffffffffffffffffffffffff) |
| 245 |
} |
||
| 246 |
/** |
||
| 247 |
* Equivalent to: |
||
| 248 |
* amount1 = roundUp |
||
| 249 |
* ? FullMath.mulDivRoundingUp(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96) |
||
| 250 |
* : FullMath.mulDiv(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96); |
||
| 251 |
* Cannot overflow because `type(uint128).max * type(uint160).max >> 96 < (1 << 192)`. |
||
| 252 |
*/ |
||
| 253 |
√ 1
|
⟳ 1
|
amount1 = FullMath.mulDiv(_liquidity, numerator, denominator); |
| 254 |
assembly ("memory-safe") {
|
||
| 255 |
√ 6
|
⟳ 6
|
amount1 := add(amount1, and(gt(mulmod(_liquidity, numerator, denominator), 0), roundUp)) |
| 256 |
} |
||
| 257 |
} |
||
| 258 | |||
| 259 |
/// @notice Helper that gets signed currency0 delta |
||
| 260 |
/// @param sqrtPriceAX96 A sqrt price |
||
| 261 |
/// @param sqrtPriceBX96 Another sqrt price |
||
| 262 |
/// @param liquidity The change in liquidity for which to compute the amount0 delta |
||
| 263 |
/// @return int256 Amount of currency0 corresponding to the passed liquidityDelta between the two prices |
||
| 264 |
function getAmount0Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity) |
||
| 265 |
internal |
||
| 266 |
pure |
||
| 267 |
√ 1
|
⟳ 1
|
returns (int256) |
| 268 |
{
|
||
| 269 |
unchecked {
|
||
| 270 |
√ 2
|
⟳ 2
|
return liquidity < 0 |
| 271 |
√ 5
|
? getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(-liquidity), false).toInt256() |
|
| 272 |
√ 5
|
⟳ 5
|
: -getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(liquidity), true).toInt256(); |
| 273 |
} |
||
| 274 |
} |
||
| 275 | |||
| 276 |
/// @notice Helper that gets signed currency1 delta |
||
| 277 |
/// @param sqrtPriceAX96 A sqrt price |
||
| 278 |
/// @param sqrtPriceBX96 Another sqrt price |
||
| 279 |
/// @param liquidity The change in liquidity for which to compute the amount1 delta |
||
| 280 |
/// @return int256 Amount of currency1 corresponding to the passed liquidityDelta between the two prices |
||
| 281 |
function getAmount1Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity) |
||
| 282 |
internal |
||
| 283 |
pure |
||
| 284 |
√ 1
|
⟳ 1
|
returns (int256) |
| 285 |
{
|
||
| 286 |
unchecked {
|
||
| 287 |
√ 2
|
⟳ 2
|
return liquidity < 0 |
| 288 |
√ 5
|
? getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(-liquidity), false).toInt256() |
|
| 289 |
√ 5
|
⟳ 5
|
: -getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(liquidity), true).toInt256(); |
| 290 |
} |
||
| 291 |
} |
||
| 292 |
} |
||
| 293 |
| Lines covered: | 0 / 96 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {PoolId} from "../types/PoolId.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {Position} from "./Position.sol";
|
||
| 7 | |||
| 8 |
/// @notice A helper library to provide state getters that use extsload |
||
| 9 |
library StateLibrary {
|
||
| 10 |
/// @notice index of pools mapping in the PoolManager |
||
| 11 |
bytes32 public constant POOLS_SLOT = bytes32(uint256(6)); |
||
| 12 | |||
| 13 |
/// @notice index of feeGrowthGlobal0X128 in Pool.State |
||
| 14 |
uint256 public constant FEE_GROWTH_GLOBAL0_OFFSET = 1; |
||
| 15 |
/// @notice index of feeGrowthGlobal1X128 in Pool.State |
||
| 16 |
uint256 public constant FEE_GROWTH_GLOBAL1_OFFSET = 2; |
||
| 17 | |||
| 18 |
/// @notice index of liquidity in Pool.State |
||
| 19 |
uint256 public constant LIQUIDITY_OFFSET = 3; |
||
| 20 | |||
| 21 |
/// @notice index of TicksInfo mapping in Pool.State: mapping(int24 => TickInfo) ticks; |
||
| 22 |
uint256 public constant TICKS_OFFSET = 4; |
||
| 23 | |||
| 24 |
/// @notice index of tickBitmap mapping in Pool.State |
||
| 25 |
uint256 public constant TICK_BITMAP_OFFSET = 5; |
||
| 26 | |||
| 27 |
/// @notice index of Position.Info mapping in Pool.State: mapping(bytes32 => Position.Info) positions; |
||
| 28 |
uint256 public constant POSITIONS_OFFSET = 6; |
||
| 29 | |||
| 30 |
/** |
||
| 31 |
* @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee |
||
| 32 |
* @dev Corresponds to pools[poolId].slot0 |
||
| 33 |
* @param manager The pool manager contract. |
||
| 34 |
* @param poolId The ID of the pool. |
||
| 35 |
* @return sqrtPriceX96 The square root of the price of the pool, in Q96 precision. |
||
| 36 |
* @return tick The current tick of the pool. |
||
| 37 |
* @return protocolFee The protocol fee of the pool. |
||
| 38 |
* @return lpFee The swap fee of the pool. |
||
| 39 |
*/ |
||
| 40 |
function getSlot0(IPoolManager manager, PoolId poolId) |
||
| 41 |
internal |
||
| 42 |
view |
||
| 43 |
returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee) |
||
| 44 |
{
|
||
| 45 |
// slot key of Pool.State value: `pools[poolId]` |
||
| 46 |
bytes32 stateSlot = _getPoolStateSlot(poolId); |
||
| 47 | |||
| 48 |
bytes32 data = manager.extsload(stateSlot); |
||
| 49 | |||
| 50 |
// 24 bits |24bits|24bits |24 bits|160 bits |
||
| 51 |
// 0x000000 |000bb8|000000 |ffff75 |0000000000000000fe3aa841ba359daa0ea9eff7 |
||
| 52 |
// ---------- | fee |protocolfee | tick | sqrtPriceX96 |
||
| 53 |
assembly ("memory-safe") {
|
||
| 54 |
// bottom 160 bits of data |
||
| 55 |
sqrtPriceX96 := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
||
| 56 |
// next 24 bits of data |
||
| 57 |
tick := signextend(2, shr(160, data)) |
||
| 58 |
// next 24 bits of data |
||
| 59 |
protocolFee := and(shr(184, data), 0xFFFFFF) |
||
| 60 |
// last 24 bits of data |
||
| 61 |
lpFee := and(shr(208, data), 0xFFFFFF) |
||
| 62 |
} |
||
| 63 |
} |
||
| 64 | |||
| 65 |
/** |
||
| 66 |
* @notice Retrieves the tick information of a pool at a specific tick. |
||
| 67 |
* @dev Corresponds to pools[poolId].ticks[tick] |
||
| 68 |
* @param manager The pool manager contract. |
||
| 69 |
* @param poolId The ID of the pool. |
||
| 70 |
* @param tick The tick to retrieve information for. |
||
| 71 |
* @return liquidityGross The total position liquidity that references this tick |
||
| 72 |
* @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) |
||
| 73 |
* @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) |
||
| 74 |
* @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) |
||
| 75 |
*/ |
||
| 76 |
function getTickInfo(IPoolManager manager, PoolId poolId, int24 tick) |
||
| 77 |
internal |
||
| 78 |
view |
||
| 79 |
returns ( |
||
| 80 |
uint128 liquidityGross, |
||
| 81 |
int128 liquidityNet, |
||
| 82 |
uint256 feeGrowthOutside0X128, |
||
| 83 |
uint256 feeGrowthOutside1X128 |
||
| 84 |
) |
||
| 85 |
{
|
||
| 86 |
bytes32 slot = _getTickInfoSlot(poolId, tick); |
||
| 87 | |||
| 88 |
// read all 3 words of the TickInfo struct |
||
| 89 |
bytes32[] memory data = manager.extsload(slot, 3); |
||
| 90 |
assembly ("memory-safe") {
|
||
| 91 |
let firstWord := mload(add(data, 32)) |
||
| 92 |
liquidityNet := sar(128, firstWord) |
||
| 93 |
liquidityGross := and(firstWord, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
||
| 94 |
feeGrowthOutside0X128 := mload(add(data, 64)) |
||
| 95 |
feeGrowthOutside1X128 := mload(add(data, 96)) |
||
| 96 |
} |
||
| 97 |
} |
||
| 98 | |||
| 99 |
/** |
||
| 100 |
* @notice Retrieves the liquidity information of a pool at a specific tick. |
||
| 101 |
* @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of getTickInfo |
||
| 102 |
* @param manager The pool manager contract. |
||
| 103 |
* @param poolId The ID of the pool. |
||
| 104 |
* @param tick The tick to retrieve liquidity for. |
||
| 105 |
* @return liquidityGross The total position liquidity that references this tick |
||
| 106 |
* @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) |
||
| 107 |
*/ |
||
| 108 |
function getTickLiquidity(IPoolManager manager, PoolId poolId, int24 tick) |
||
| 109 |
internal |
||
| 110 |
view |
||
| 111 |
returns (uint128 liquidityGross, int128 liquidityNet) |
||
| 112 |
{
|
||
| 113 |
bytes32 slot = _getTickInfoSlot(poolId, tick); |
||
| 114 | |||
| 115 |
bytes32 value = manager.extsload(slot); |
||
| 116 |
assembly ("memory-safe") {
|
||
| 117 |
liquidityNet := sar(128, value) |
||
| 118 |
liquidityGross := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
||
| 119 |
} |
||
| 120 |
} |
||
| 121 | |||
| 122 |
/** |
||
| 123 |
* @notice Retrieves the fee growth outside a tick range of a pool |
||
| 124 |
* @dev Corresponds to pools[poolId].ticks[tick].feeGrowthOutside0X128 and pools[poolId].ticks[tick].feeGrowthOutside1X128. A more gas efficient version of getTickInfo |
||
| 125 |
* @param manager The pool manager contract. |
||
| 126 |
* @param poolId The ID of the pool. |
||
| 127 |
* @param tick The tick to retrieve fee growth for. |
||
| 128 |
* @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) |
||
| 129 |
* @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) |
||
| 130 |
*/ |
||
| 131 |
function getTickFeeGrowthOutside(IPoolManager manager, PoolId poolId, int24 tick) |
||
| 132 |
internal |
||
| 133 |
view |
||
| 134 |
returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) |
||
| 135 |
{
|
||
| 136 |
bytes32 slot = _getTickInfoSlot(poolId, tick); |
||
| 137 | |||
| 138 |
// offset by 1 word, since the first word is liquidityGross + liquidityNet |
||
| 139 |
bytes32[] memory data = manager.extsload(bytes32(uint256(slot) + 1), 2); |
||
| 140 |
assembly ("memory-safe") {
|
||
| 141 |
feeGrowthOutside0X128 := mload(add(data, 32)) |
||
| 142 |
feeGrowthOutside1X128 := mload(add(data, 64)) |
||
| 143 |
} |
||
| 144 |
} |
||
| 145 | |||
| 146 |
/** |
||
| 147 |
* @notice Retrieves the global fee growth of a pool. |
||
| 148 |
* @dev Corresponds to pools[poolId].feeGrowthGlobal0X128 and pools[poolId].feeGrowthGlobal1X128 |
||
| 149 |
* @param manager The pool manager contract. |
||
| 150 |
* @param poolId The ID of the pool. |
||
| 151 |
* @return feeGrowthGlobal0 The global fee growth for token0. |
||
| 152 |
* @return feeGrowthGlobal1 The global fee growth for token1. |
||
| 153 |
*/ |
||
| 154 |
function getFeeGrowthGlobals(IPoolManager manager, PoolId poolId) |
||
| 155 |
internal |
||
| 156 |
view |
||
| 157 |
returns (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) |
||
| 158 |
{
|
||
| 159 |
// slot key of Pool.State value: `pools[poolId]` |
||
| 160 |
bytes32 stateSlot = _getPoolStateSlot(poolId); |
||
| 161 | |||
| 162 |
// Pool.State, `uint256 feeGrowthGlobal0X128` |
||
| 163 |
bytes32 slot_feeGrowthGlobal0X128 = bytes32(uint256(stateSlot) + FEE_GROWTH_GLOBAL0_OFFSET); |
||
| 164 | |||
| 165 |
// read the 2 words of feeGrowthGlobal |
||
| 166 |
bytes32[] memory data = manager.extsload(slot_feeGrowthGlobal0X128, 2); |
||
| 167 |
assembly ("memory-safe") {
|
||
| 168 |
feeGrowthGlobal0 := mload(add(data, 32)) |
||
| 169 |
feeGrowthGlobal1 := mload(add(data, 64)) |
||
| 170 |
} |
||
| 171 |
} |
||
| 172 | |||
| 173 |
/** |
||
| 174 |
* @notice Retrieves total the liquidity of a pool. |
||
| 175 |
* @dev Corresponds to pools[poolId].liquidity |
||
| 176 |
* @param manager The pool manager contract. |
||
| 177 |
* @param poolId The ID of the pool. |
||
| 178 |
* @return liquidity The liquidity of the pool. |
||
| 179 |
*/ |
||
| 180 |
function getLiquidity(IPoolManager manager, PoolId poolId) internal view returns (uint128 liquidity) {
|
||
| 181 |
// slot key of Pool.State value: `pools[poolId]` |
||
| 182 |
bytes32 stateSlot = _getPoolStateSlot(poolId); |
||
| 183 | |||
| 184 |
// Pool.State: `uint128 liquidity` |
||
| 185 |
bytes32 slot = bytes32(uint256(stateSlot) + LIQUIDITY_OFFSET); |
||
| 186 | |||
| 187 |
liquidity = uint128(uint256(manager.extsload(slot))); |
||
| 188 |
} |
||
| 189 | |||
| 190 |
/** |
||
| 191 |
* @notice Retrieves the tick bitmap of a pool at a specific tick. |
||
| 192 |
* @dev Corresponds to pools[poolId].tickBitmap[tick] |
||
| 193 |
* @param manager The pool manager contract. |
||
| 194 |
* @param poolId The ID of the pool. |
||
| 195 |
* @param tick The tick to retrieve the bitmap for. |
||
| 196 |
* @return tickBitmap The bitmap of the tick. |
||
| 197 |
*/ |
||
| 198 |
function getTickBitmap(IPoolManager manager, PoolId poolId, int16 tick) |
||
| 199 |
internal |
||
| 200 |
view |
||
| 201 |
returns (uint256 tickBitmap) |
||
| 202 |
{
|
||
| 203 |
// slot key of Pool.State value: `pools[poolId]` |
||
| 204 |
bytes32 stateSlot = _getPoolStateSlot(poolId); |
||
| 205 | |||
| 206 |
// Pool.State: `mapping(int16 => uint256) tickBitmap;` |
||
| 207 |
bytes32 tickBitmapMapping = bytes32(uint256(stateSlot) + TICK_BITMAP_OFFSET); |
||
| 208 | |||
| 209 |
// slot id of the mapping key: `pools[poolId].tickBitmap[tick] |
||
| 210 |
bytes32 slot = keccak256(abi.encodePacked(int256(tick), tickBitmapMapping)); |
||
| 211 | |||
| 212 |
tickBitmap = uint256(manager.extsload(slot)); |
||
| 213 |
} |
||
| 214 | |||
| 215 |
/** |
||
| 216 |
* @notice Retrieves the position information of a pool at a specific position ID. |
||
| 217 |
* @dev Corresponds to pools[poolId].positions[positionId] |
||
| 218 |
* @param manager The pool manager contract. |
||
| 219 |
* @param poolId The ID of the pool. |
||
| 220 |
* @param positionId The ID of the position. |
||
| 221 |
* @return liquidity The liquidity of the position. |
||
| 222 |
* @return feeGrowthInside0LastX128 The fee growth inside the position for token0. |
||
| 223 |
* @return feeGrowthInside1LastX128 The fee growth inside the position for token1. |
||
| 224 |
*/ |
||
| 225 |
function getPositionInfo(IPoolManager manager, PoolId poolId, bytes32 positionId) |
||
| 226 |
internal |
||
| 227 |
view |
||
| 228 |
returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) |
||
| 229 |
{
|
||
| 230 |
bytes32 slot = _getPositionInfoSlot(poolId, positionId); |
||
| 231 | |||
| 232 |
// read all 3 words of the Position.Info struct |
||
| 233 |
bytes32[] memory data = manager.extsload(slot, 3); |
||
| 234 | |||
| 235 |
assembly ("memory-safe") {
|
||
| 236 |
liquidity := mload(add(data, 32)) |
||
| 237 |
feeGrowthInside0LastX128 := mload(add(data, 64)) |
||
| 238 |
feeGrowthInside1LastX128 := mload(add(data, 96)) |
||
| 239 |
} |
||
| 240 |
} |
||
| 241 | |||
| 242 |
function getPosition( |
||
| 243 |
IPoolManager manager, |
||
| 244 |
PoolId poolId, |
||
| 245 |
address owner, |
||
| 246 |
int24 tickLower, |
||
| 247 |
int24 tickUpper, |
||
| 248 |
bytes32 salt |
||
| 249 |
) internal view returns (Position.Info memory) {
|
||
| 250 |
// positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)) |
||
| 251 |
bytes32 positionKey; |
||
| 252 | |||
| 253 |
assembly ("memory-safe") {
|
||
| 254 |
let fmp := mload(0x40) |
||
| 255 |
mstore(add(fmp, 0x26), salt) // [0x26, 0x46) |
||
| 256 |
mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26) |
||
| 257 |
mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23) |
||
| 258 |
mstore(fmp, owner) // [0x0c, 0x20) |
||
| 259 |
positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes |
||
| 260 | |||
| 261 |
// now clean the memory we used |
||
| 262 |
mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt |
||
| 263 |
mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt |
||
| 264 |
mstore(fmp, 0) // fmp held owner |
||
| 265 |
} |
||
| 266 |
(uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) = |
||
| 267 |
getPositionInfo(manager, poolId, positionKey); |
||
| 268 |
return Position.Info({
|
||
| 269 |
liquidity: liquidity, |
||
| 270 |
feeGrowthInside0LastX128: feeGrowthInside0LastX128, |
||
| 271 |
feeGrowthInside1LastX128: feeGrowthInside1LastX128 |
||
| 272 |
}); |
||
| 273 |
} |
||
| 274 | |||
| 275 |
/** |
||
| 276 |
* @notice Retrieves the liquidity of a position. |
||
| 277 |
* @dev Corresponds to pools[poolId].positions[positionId].liquidity. A more gas efficient version of getPositionInfo |
||
| 278 |
* @param manager The pool manager contract. |
||
| 279 |
* @param poolId The ID of the pool. |
||
| 280 |
* @param positionId The ID of the position. |
||
| 281 |
* @return liquidity The liquidity of the position. |
||
| 282 |
*/ |
||
| 283 |
function getPositionLiquidity(IPoolManager manager, PoolId poolId, bytes32 positionId) |
||
| 284 |
internal |
||
| 285 |
view |
||
| 286 |
returns (uint128 liquidity) |
||
| 287 |
{
|
||
| 288 |
bytes32 slot = _getPositionInfoSlot(poolId, positionId); |
||
| 289 |
liquidity = uint128(uint256(manager.extsload(slot))); |
||
| 290 |
} |
||
| 291 | |||
| 292 |
/** |
||
| 293 |
* @notice Live calculate the fee growth inside a tick range of a pool |
||
| 294 |
* @dev pools[poolId].feeGrowthInside0LastX128 in Position.Info is cached and can become stale. This function will live calculate the feeGrowthInside |
||
| 295 |
* @param manager The pool manager contract. |
||
| 296 |
* @param poolId The ID of the pool. |
||
| 297 |
* @param tickLower The lower tick of the range. |
||
| 298 |
* @param tickUpper The upper tick of the range. |
||
| 299 |
* @return feeGrowthInside0X128 The fee growth inside the tick range for token0. |
||
| 300 |
* @return feeGrowthInside1X128 The fee growth inside the tick range for token1. |
||
| 301 |
*/ |
||
| 302 |
function getFeeGrowthInside(IPoolManager manager, PoolId poolId, int24 tickLower, int24 tickUpper) |
||
| 303 |
internal |
||
| 304 |
view |
||
| 305 |
returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) |
||
| 306 |
{
|
||
| 307 |
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = getFeeGrowthGlobals(manager, poolId); |
||
| 308 | |||
| 309 |
(uint256 lowerFeeGrowthOutside0X128, uint256 lowerFeeGrowthOutside1X128) = |
||
| 310 |
getTickFeeGrowthOutside(manager, poolId, tickLower); |
||
| 311 |
(uint256 upperFeeGrowthOutside0X128, uint256 upperFeeGrowthOutside1X128) = |
||
| 312 |
getTickFeeGrowthOutside(manager, poolId, tickUpper); |
||
| 313 |
(, int24 tickCurrent,,) = getSlot0(manager, poolId); |
||
| 314 |
unchecked {
|
||
| 315 |
if (tickCurrent < tickLower) {
|
||
| 316 |
feeGrowthInside0X128 = lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128; |
||
| 317 |
feeGrowthInside1X128 = lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128; |
||
| 318 |
} else if (tickCurrent >= tickUpper) {
|
||
| 319 |
feeGrowthInside0X128 = upperFeeGrowthOutside0X128 - lowerFeeGrowthOutside0X128; |
||
| 320 |
feeGrowthInside1X128 = upperFeeGrowthOutside1X128 - lowerFeeGrowthOutside1X128; |
||
| 321 |
} else {
|
||
| 322 |
feeGrowthInside0X128 = feeGrowthGlobal0X128 - lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128; |
||
| 323 |
feeGrowthInside1X128 = feeGrowthGlobal1X128 - lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128; |
||
| 324 |
} |
||
| 325 |
} |
||
| 326 |
} |
||
| 327 | |||
| 328 |
function _getPoolStateSlot(PoolId poolId) internal pure returns (bytes32) {
|
||
| 329 |
return keccak256(abi.encodePacked(PoolId.unwrap(poolId), POOLS_SLOT)); |
||
| 330 |
} |
||
| 331 | |||
| 332 |
function _getTickInfoSlot(PoolId poolId, int24 tick) internal pure returns (bytes32) {
|
||
| 333 |
// slot key of Pool.State value: `pools[poolId]` |
||
| 334 |
bytes32 stateSlot = _getPoolStateSlot(poolId); |
||
| 335 | |||
| 336 |
// Pool.State: `mapping(int24 => TickInfo) ticks` |
||
| 337 |
bytes32 ticksMappingSlot = bytes32(uint256(stateSlot) + TICKS_OFFSET); |
||
| 338 | |||
| 339 |
// slot key of the tick key: `pools[poolId].ticks[tick] |
||
| 340 |
return keccak256(abi.encodePacked(int256(tick), ticksMappingSlot)); |
||
| 341 |
} |
||
| 342 | |||
| 343 |
function _getPositionInfoSlot(PoolId poolId, bytes32 positionId) internal pure returns (bytes32) {
|
||
| 344 |
// slot key of Pool.State value: `pools[poolId]` |
||
| 345 |
bytes32 stateSlot = _getPoolStateSlot(poolId); |
||
| 346 | |||
| 347 |
// Pool.State: `mapping(bytes32 => Position.Info) positions;` |
||
| 348 |
bytes32 positionMapping = bytes32(uint256(stateSlot) + POSITIONS_OFFSET); |
||
| 349 | |||
| 350 |
// slot of the mapping key: `pools[poolId].positions[positionId] |
||
| 351 |
return keccak256(abi.encodePacked(positionId, positionMapping)); |
||
| 352 |
} |
||
| 353 |
} |
||
| 354 |
| Lines covered: | 39 / 41 (95.1%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {FullMath} from "./FullMath.sol";
|
||
| 5 |
import {SqrtPriceMath} from "./SqrtPriceMath.sol";
|
||
| 6 | |||
| 7 |
/// @title Computes the result of a swap within ticks |
||
| 8 |
/// @notice Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick. |
||
| 9 |
library SwapMath {
|
||
| 10 |
√ 5045
|
⟳ 10409
|
uint256 internal constant MAX_FEE_PIPS = 1e6; |
| 11 | |||
| 12 |
/// @notice Computes the sqrt price target for the next swap step |
||
| 13 |
/// @param zeroForOne The direction of the swap, true for currency0 to currency1, false for currency1 to currency0 |
||
| 14 |
/// @param sqrtPriceNextX96 The Q64.96 sqrt price for the next initialized tick |
||
| 15 |
/// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value |
||
| 16 |
/// after the swap. If one for zero, the price cannot be greater than this value after the swap |
||
| 17 |
/// @return sqrtPriceTargetX96 The price target for the next swap step |
||
| 18 |
function getSqrtPriceTarget(bool zeroForOne, uint160 sqrtPriceNextX96, uint160 sqrtPriceLimitX96) |
||
| 19 |
internal |
||
| 20 |
pure |
||
| 21 |
returns (uint160 sqrtPriceTargetX96) |
||
| 22 |
{
|
||
| 23 |
assembly ("memory-safe") {
|
||
| 24 |
// a flag to toggle between sqrtPriceNextX96 and sqrtPriceLimitX96 |
||
| 25 |
// when zeroForOne == true, nextOrLimit reduces to sqrtPriceNextX96 >= sqrtPriceLimitX96 |
||
| 26 |
// sqrtPriceTargetX96 = max(sqrtPriceNextX96, sqrtPriceLimitX96) |
||
| 27 |
// when zeroForOne == false, nextOrLimit reduces to sqrtPriceNextX96 < sqrtPriceLimitX96 |
||
| 28 |
// sqrtPriceTargetX96 = min(sqrtPriceNextX96, sqrtPriceLimitX96) |
||
| 29 |
sqrtPriceNextX96 := and(sqrtPriceNextX96, 0xffffffffffffffffffffffffffffffffffffffff) |
||
| 30 |
√ 790
|
⟳ 6
|
sqrtPriceLimitX96 := and(sqrtPriceLimitX96, 0xffffffffffffffffffffffffffffffffffffffff) |
| 31 |
√ 395
|
⟳ 3
|
let nextOrLimit := xor(lt(sqrtPriceNextX96, sqrtPriceLimitX96), and(zeroForOne, 0xff)) |
| 32 |
√ 1185
|
⟳ 9
|
let symDiff := xor(sqrtPriceNextX96, sqrtPriceLimitX96) |
| 33 |
√ 1580
|
⟳ 12
|
sqrtPriceTargetX96 := xor(sqrtPriceLimitX96, mul(symDiff, nextOrLimit)) |
| 34 |
} |
||
| 35 |
} |
||
| 36 | |||
| 37 |
/// @notice Computes the result of swapping some amount in, or amount out, given the parameters of the swap |
||
| 38 |
/// @dev If the swap's amountSpecified is negative, the combined fee and input amount will never exceed the absolute value of the remaining amount. |
||
| 39 |
/// @param sqrtPriceCurrentX96 The current sqrt price of the pool |
||
| 40 |
/// @param sqrtPriceTargetX96 The price that cannot be exceeded, from which the direction of the swap is inferred |
||
| 41 |
/// @param liquidity The usable liquidity |
||
| 42 |
/// @param amountRemaining How much input or output amount is remaining to be swapped in/out |
||
| 43 |
/// @param feePips The fee taken from the input amount, expressed in hundredths of a bip |
||
| 44 |
/// @return sqrtPriceNextX96 The price after swapping the amount in/out, not to exceed the price target |
||
| 45 |
/// @return amountIn The amount to be swapped in, of either currency0 or currency1, based on the direction of the swap |
||
| 46 |
/// @return amountOut The amount to be received, of either currency0 or currency1, based on the direction of the swap |
||
| 47 |
/// @return feeAmount The amount of input that will be taken as a fee/ |
||
| 48 |
/// @dev feePips must be no larger than MAX_FEE_PIPS for this function. We ensure that before setting a fee using LPFeeLibrary.isValid. |
||
| 49 |
function computeSwapStep( |
||
| 50 |
uint160 sqrtPriceCurrentX96, |
||
| 51 |
uint160 sqrtPriceTargetX96, |
||
| 52 |
uint128 liquidity, |
||
| 53 |
int256 amountRemaining, |
||
| 54 |
uint24 feePips |
||
| 55 |
√ 1580
|
⟳ 12
|
) internal pure returns (uint160 sqrtPriceNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) {
|
| 56 |
unchecked {
|
||
| 57 |
√ 1185
|
⟳ 9
|
uint256 _feePips = feePips; // upcast once and cache |
| 58 |
√ 3555
|
⟳ 27
|
bool zeroForOne = sqrtPriceCurrentX96 >= sqrtPriceTargetX96; |
| 59 |
√ 1185
|
⟳ 9
|
bool exactIn = amountRemaining < 0; |
| 60 | |||
| 61 |
if (exactIn) {
|
||
| 62 |
√ 395
|
⟳ 3
|
uint256 amountRemainingLessFee = |
| 63 |
√ 1185
|
⟳ 9
|
FullMath.mulDiv(uint256(-amountRemaining), MAX_FEE_PIPS - _feePips, MAX_FEE_PIPS); |
| 64 |
√ 395
|
⟳ 3
|
amountIn = zeroForOne |
| 65 |
√ 17335
|
⟳ 15
|
? SqrtPriceMath.getAmount0Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, true) |
| 66 |
√ 1975
|
⟳ 34670
|
: SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, true); |
| 67 |
√ 790
|
⟳ 6
|
if (amountRemainingLessFee >= amountIn) {
|
| 68 |
// `amountIn` is capped by the target price |
||
| 69 |
√ 394
|
⟳ 2
|
sqrtPriceNextX96 = sqrtPriceTargetX96; |
| 70 |
√ 394
|
⟳ 2
|
feeAmount = _feePips == MAX_FEE_PIPS |
| 71 |
√ 3467
|
⟳ 2
|
? amountIn |
| 72 |
√ 1576
|
⟳ 13868
|
: FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_FEE_PIPS - _feePips); |
| 73 |
} else {
|
||
| 74 |
√ 1
|
⟳ 1
|
sqrtPriceNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( |
| 75 |
√ 4
|
⟳ 4
|
sqrtPriceCurrentX96, liquidity, amountRemainingLessFee, zeroForOne |
| 76 |
); |
||
| 77 |
√ 1
|
⟳ 1
|
amountIn = zeroForOne |
| 78 |
√ 5
|
⟳ 5
|
? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true) |
| 79 |
√ 5
|
⟳ 5
|
: SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true); |
| 80 |
// we didn't reach the target, so take the remainder of the maximum input as fee |
||
| 81 |
√ 2
|
⟳ 2
|
feeAmount = uint256(-amountRemaining) - amountIn; |
| 82 |
} |
||
| 83 |
√ 395
|
⟳ 3
|
amountOut = zeroForOne |
| 84 |
√ 17335
|
⟳ 15
|
? SqrtPriceMath.getAmount1Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, false) |
| 85 |
√ 1975
|
⟳ 34670
|
: SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, false); |
| 86 |
} else {
|
||
| 87 |
√ 3467
|
⟳ 6934
|
amountOut = zeroForOne |
| 88 |
√ 17335
|
⟳ 5
|
? SqrtPriceMath.getAmount1Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, false) |
| 89 |
√ 17335
|
⟳ 34670
|
: SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, false); |
| 90 |
√ 6934
|
⟳ 13868
|
if (uint256(amountRemaining) >= amountOut) {
|
| 91 |
// `amountOut` is capped by the target price |
||
| 92 |
√ 3467
|
⟳ 6934
|
sqrtPriceNextX96 = sqrtPriceTargetX96; |
| 93 |
} else {
|
||
| 94 |
// cap the output amount to not exceed the remaining output amount |
||
| 95 |
√ 1
|
⟳ 1
|
amountOut = uint256(amountRemaining); |
| 96 |
sqrtPriceNextX96 = |
||
| 97 |
√ 5
|
⟳ 5
|
SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtPriceCurrentX96, liquidity, amountOut, zeroForOne); |
| 98 |
} |
||
| 99 |
√ 3467
|
⟳ 6934
|
amountIn = zeroForOne |
| 100 |
√ 17335
|
⟳ 5
|
? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true) |
| 101 |
√ 17335
|
⟳ 34670
|
: SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true); |
| 102 |
// `feePips` cannot be `MAX_FEE_PIPS` for exact out |
||
| 103 |
√ 13868
|
⟳ 27736
|
feeAmount = FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_FEE_PIPS - _feePips); |
| 104 |
} |
||
| 105 |
} |
||
| 106 |
} |
||
| 107 |
} |
||
| 108 |
| Lines covered: | 32 / 34 (94.1%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {BitMath} from "./BitMath.sol";
|
||
| 5 | |||
| 6 |
/// @title Packed tick initialized state library |
||
| 7 |
/// @notice Stores a packed mapping of tick index to its initialized state |
||
| 8 |
/// @dev The mapping uses int16 for keys since ticks are represented as int24 and there are 256 (2^8) values per word. |
||
| 9 |
library TickBitmap {
|
||
| 10 |
/// @notice Thrown when the tick is not enumerated by the tick spacing |
||
| 11 |
/// @param tick the invalid tick |
||
| 12 |
/// @param tickSpacing The tick spacing of the pool |
||
| 13 |
error TickMisaligned(int24 tick, int24 tickSpacing); |
||
| 14 | |||
| 15 |
/// @dev round towards negative infinity |
||
| 16 |
function compress(int24 tick, int24 tickSpacing) internal pure returns (int24 compressed) {
|
||
| 17 |
// compressed = tick / tickSpacing; |
||
| 18 |
// if (tick < 0 && tick % tickSpacing != 0) compressed--; |
||
| 19 |
assembly ("memory-safe") {
|
||
| 20 |
√ 395
|
⟳ 3
|
tick := signextend(2, tick) |
| 21 |
√ 1185
|
⟳ 9
|
tickSpacing := signextend(2, tickSpacing) |
| 22 |
compressed := |
||
| 23 |
sub( |
||
| 24 |
√ 1185
|
⟳ 9
|
sdiv(tick, tickSpacing), |
| 25 |
// if (tick < 0 && tick % tickSpacing != 0) then tick % tickSpacing < 0, vice versa |
||
| 26 |
√ 1185
|
⟳ 9
|
slt(smod(tick, tickSpacing), 0) |
| 27 |
) |
||
| 28 |
} |
||
| 29 |
} |
||
| 30 | |||
| 31 |
/// @notice Computes the position in the mapping where the initialized bit for a tick lives |
||
| 32 |
/// @param tick The tick for which to compute the position |
||
| 33 |
/// @return wordPos The key in the mapping containing the word in which the bit is stored |
||
| 34 |
/// @return bitPos The bit position in the word where the flag is stored |
||
| 35 |
function position(int24 tick) internal pure returns (int16 wordPos, uint8 bitPos) {
|
||
| 36 |
assembly ("memory-safe") {
|
||
| 37 |
// signed arithmetic shift right |
||
| 38 |
√ 7724
|
⟳ 13874
|
wordPos := sar(8, signextend(2, tick)) |
| 39 |
√ 3862
|
⟳ 6937
|
bitPos := and(tick, 0xff) |
| 40 |
} |
||
| 41 |
} |
||
| 42 | |||
| 43 |
/// @notice Flips the initialized state for a given tick from false to true, or vice versa |
||
| 44 |
/// @param self The mapping in which to flip the tick |
||
| 45 |
/// @param tick The tick to flip |
||
| 46 |
/// @param tickSpacing The spacing between usable ticks |
||
| 47 |
function flipTick(mapping(int16 => uint256) storage self, int24 tick, int24 tickSpacing) internal {
|
||
| 48 |
// Equivalent to the following Solidity: |
||
| 49 |
// if (tick % tickSpacing != 0) revert TickMisaligned(tick, tickSpacing); |
||
| 50 |
// (int16 wordPos, uint8 bitPos) = position(tick / tickSpacing); |
||
| 51 |
// uint256 mask = 1 << bitPos; |
||
| 52 |
// self[wordPos] ^= mask; |
||
| 53 |
assembly ("memory-safe") {
|
||
| 54 |
√ 2
|
⟳ 2
|
tick := signextend(2, tick) |
| 55 |
√ 2
|
⟳ 2
|
tickSpacing := signextend(2, tickSpacing) |
| 56 |
// ensure that the tick is spaced |
||
| 57 |
√ 6
|
⟳ 6
|
if smod(tick, tickSpacing) {
|
| 58 |
⟳ 1
|
let fmp := mload(0x40) |
|
| 59 |
⟳ 2
|
mstore(fmp, 0xd4d8f3e6) // selector for TickMisaligned(int24,int24) |
|
| 60 |
⟳ 3
|
mstore(add(fmp, 0x20), tick) |
|
| 61 |
⟳ 3
|
mstore(add(fmp, 0x40), tickSpacing) |
|
| 62 |
⟳ 3
|
revert(add(fmp, 0x1c), 0x44) |
|
| 63 |
} |
||
| 64 |
√ 4
|
⟳ 4
|
tick := sdiv(tick, tickSpacing) |
| 65 |
// calculate the storage slot corresponding to the tick |
||
| 66 |
// wordPos = tick >> 8 |
||
| 67 |
√ 6
|
⟳ 6
|
mstore(0, sar(8, tick)) |
| 68 |
√ 4
|
⟳ 4
|
mstore(0x20, self.slot) |
| 69 |
// the slot of self[wordPos] is keccak256(abi.encode(wordPos, self.slot)) |
||
| 70 |
√ 4
|
⟳ 4
|
let slot := keccak256(0, 0x40) |
| 71 |
// mask = 1 << bitPos = 1 << (tick % 256) |
||
| 72 |
// self[wordPos] ^= mask |
||
| 73 |
√ 10
|
⟳ 10
|
sstore(slot, xor(sload(slot), shl(and(tick, 0xff), 1))) |
| 74 |
} |
||
| 75 |
} |
||
| 76 | |||
| 77 |
/// @notice Returns the next initialized tick contained in the same word (or adjacent word) as the tick that is either |
||
| 78 |
/// to the left (less than or equal to) or right (greater than) of the given tick |
||
| 79 |
/// @param self The mapping in which to compute the next initialized tick |
||
| 80 |
/// @param tick The starting tick |
||
| 81 |
/// @param tickSpacing The spacing between usable ticks |
||
| 82 |
/// @param lte Whether to search for the next initialized tick to the left (less than or equal to the starting tick) |
||
| 83 |
/// @return next The next initialized or uninitialized tick up to 256 ticks away from the current tick |
||
| 84 |
/// @return initialized Whether the next tick is initialized, as the function only searches within up to 256 ticks |
||
| 85 |
function nextInitializedTickWithinOneWord( |
||
| 86 |
mapping(int16 => uint256) storage self, |
||
| 87 |
int24 tick, |
||
| 88 |
int24 tickSpacing, |
||
| 89 |
bool lte |
||
| 90 |
√ 790
|
⟳ 6
|
) internal view returns (int24 next, bool initialized) {
|
| 91 |
unchecked {
|
||
| 92 |
int24 compressed = compress(tick, tickSpacing); |
||
| 93 | |||
| 94 |
if (lte) {
|
||
| 95 |
√ 3467
|
⟳ 3
|
(int16 wordPos, uint8 bitPos) = position(compressed); |
| 96 |
// all the 1s at or to the right of the current bitPos |
||
| 97 |
√ 13868
|
⟳ 12
|
uint256 mask = (1 << (uint256(bitPos) + 1)) - 1; |
| 98 |
√ 48538
|
⟳ 42
|
uint256 masked = self[wordPos] & mask; |
| 99 | |||
| 100 |
// if there are no initialized ticks to the right of or at the current tick, return rightmost in the word |
||
| 101 |
√ 17335
|
⟳ 15
|
initialized = masked != 0; |
| 102 |
// overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick |
||
| 103 |
next = initialized |
||
| 104 |
√ 5
|
⟳ 10
|
? (compressed - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * tickSpacing |
| 105 |
√ 10398
|
⟳ 3
|
: (compressed - int24(uint24(bitPos))) * tickSpacing; |
| 106 |
} else {
|
||
| 107 |
// start from the word of the next tick, since the current tick state doesn't matter |
||
| 108 |
√ 2765
|
⟳ 48538
|
(int16 wordPos, uint8 bitPos) = position(++compressed); |
| 109 |
// all the 1s at or to the left of the bitPos |
||
| 110 |
√ 1185
|
⟳ 20802
|
uint256 mask = ~((1 << bitPos) - 1); |
| 111 |
√ 5530
|
⟳ 97076
|
uint256 masked = self[wordPos] & mask; |
| 112 | |||
| 113 |
// if there are no initialized ticks to the left of the current tick, return leftmost in the word |
||
| 114 |
√ 1975
|
⟳ 34670
|
initialized = masked != 0; |
| 115 |
// overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick |
||
| 116 |
next = initialized |
||
| 117 |
√ 5
|
⟳ 10
|
? (compressed + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * tickSpacing |
| 118 |
√ 1576
|
⟳ 27728
|
: (compressed + int24(uint24(type(uint8).max - bitPos))) * tickSpacing; |
| 119 |
} |
||
| 120 |
} |
||
| 121 |
} |
||
| 122 |
} |
||
| 123 |
| Lines covered: | 121 / 126 (96.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {CustomRevert} from "./CustomRevert.sol";
|
||
| 5 | |||
| 6 |
/// @title Math library for computing sqrt prices from ticks and vice versa |
||
| 7 |
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports |
||
| 8 |
/// prices between 2**-128 and 2**128 |
||
| 9 |
library TickMath {
|
||
| 10 |
using CustomRevert for bytes4; |
||
| 11 | |||
| 12 |
/// @notice Thrown when the tick passed to #getSqrtPriceAtTick is not between MIN_TICK and MAX_TICK |
||
| 13 |
error InvalidTick(int24 tick); |
||
| 14 |
/// @notice Thrown when the price passed to #getTickAtSqrtPrice does not correspond to a price between MIN_TICK and MAX_TICK |
||
| 15 |
error InvalidSqrtPrice(uint160 sqrtPriceX96); |
||
| 16 | |||
| 17 |
/// @dev The minimum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**-128 |
||
| 18 |
√ 398
|
⟳ 6
|
int24 internal constant MIN_TICK = -887272; |
| 19 |
/// @dev The maximum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**128 |
||
| 20 |
√ 399
|
⟳ 7
|
int24 internal constant MAX_TICK = 887272; |
| 21 | |||
| 22 |
/// @dev The minimum tick spacing value drawn from the range of type int16 that is greater than 0, i.e. min from the range [1, 32767] |
||
| 23 |
√ 1
|
⟳ 1
|
int24 internal constant MIN_TICK_SPACING = 1; |
| 24 |
/// @dev The maximum tick spacing value drawn from the range of type int16, i.e. max from the range [1, 32767] |
||
| 25 |
√ 1
|
⟳ 1
|
int24 internal constant MAX_TICK_SPACING = type(int16).max; |
| 26 | |||
| 27 |
/// @dev The minimum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MIN_TICK) |
||
| 28 |
√ 1
|
⟳ 1
|
uint160 internal constant MIN_SQRT_PRICE = 4295128739; |
| 29 |
/// @dev The maximum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MAX_TICK) |
||
| 30 |
√ 1
|
⟳ 1
|
uint160 internal constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342; |
| 31 |
/// @dev A threshold used for optimized bounds check, equals `MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1` |
||
| 32 |
uint160 internal constant MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE = |
||
| 33 |
√ 1
|
⟳ 1
|
1461446703485210103287273052203988822378723970342 - 4295128739 - 1; |
| 34 | |||
| 35 |
/// @notice Given a tickSpacing, compute the maximum usable tick |
||
| 36 |
function maxUsableTick(int24 tickSpacing) internal pure returns (int24) {
|
||
| 37 |
unchecked {
|
||
| 38 |
return (MAX_TICK / tickSpacing) * tickSpacing; |
||
| 39 |
} |
||
| 40 |
} |
||
| 41 | |||
| 42 |
/// @notice Given a tickSpacing, compute the minimum usable tick |
||
| 43 |
function minUsableTick(int24 tickSpacing) internal pure returns (int24) {
|
||
| 44 |
unchecked {
|
||
| 45 |
return (MIN_TICK / tickSpacing) * tickSpacing; |
||
| 46 |
} |
||
| 47 |
} |
||
| 48 | |||
| 49 |
/// @notice Calculates sqrt(1.0001^tick) * 2^96 |
||
| 50 |
/// @dev Throws if |tick| > max tick |
||
| 51 |
/// @param tick The input tick for the above formula |
||
| 52 |
/// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the price of the two assets (currency1/currency0) |
||
| 53 |
/// at the given tick |
||
| 54 |
√ 1
|
⟳ 1
|
function getSqrtPriceAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
|
| 55 |
unchecked {
|
||
| 56 |
uint256 absTick; |
||
| 57 |
assembly ("memory-safe") {
|
||
| 58 |
√ 1
|
⟳ 1
|
tick := signextend(2, tick) |
| 59 |
// mask = 0 if tick >= 0 else -1 (all 1s) |
||
| 60 |
√ 1
|
⟳ 1
|
let mask := sar(255, tick) |
| 61 |
// if tick >= 0, |tick| = tick = 0 ^ tick |
||
| 62 |
// if tick < 0, |tick| = ~~|tick| = ~(-|tick| - 1) = ~(tick - 1) = (-1) ^ (tick - 1) |
||
| 63 |
// either way, |tick| = mask ^ (tick + mask) |
||
| 64 |
√ 3
|
⟳ 3
|
absTick := xor(mask, add(mask, tick)) |
| 65 |
} |
||
| 66 | |||
| 67 |
√ 2
|
⟳ 2
|
if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick); |
| 68 | |||
| 69 |
// Equivalent to: |
||
| 70 |
// price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; |
||
| 71 |
// or price = int(2**128 / sqrt(1.0001)) if (absTick & 0x1) else 1 << 128 |
||
| 72 |
uint256 price; |
||
| 73 |
assembly ("memory-safe") {
|
||
| 74 |
√ 2
|
⟳ 2
|
price := xor(shl(128, 1), mul(xor(shl(128, 1), 0xfffcb933bd6fad37aa2d162d1a594001), and(absTick, 0x1))) |
| 75 |
} |
||
| 76 |
√ 3
|
⟳ 3
|
if (absTick & 0x2 != 0) price = (price * 0xfff97272373d413259a46990580e213a) >> 128; |
| 77 |
√ 3
|
⟳ 3
|
if (absTick & 0x4 != 0) price = (price * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; |
| 78 |
√ 3
|
⟳ 3
|
if (absTick & 0x8 != 0) price = (price * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; |
| 79 |
√ 3
|
⟳ 3
|
if (absTick & 0x10 != 0) price = (price * 0xffcb9843d60f6159c9db58835c926644) >> 128; |
| 80 |
√ 791
|
⟳ 3
|
if (absTick & 0x20 != 0) price = (price * 0xff973b41fa98c081472e6896dfb254c0) >> 128; |
| 81 |
√ 3
|
⟳ 3
|
if (absTick & 0x40 != 0) price = (price * 0xff2ea16466c96a3843ec78b326b52861) >> 128; |
| 82 |
√ 3
|
⟳ 3
|
if (absTick & 0x80 != 0) price = (price * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; |
| 83 |
√ 397
|
⟳ 3
|
if (absTick & 0x100 != 0) price = (price * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; |
| 84 |
√ 393
|
⟳ 3
|
if (absTick & 0x200 != 0) price = (price * 0xf987a7253ac413176f2b074cf7815e54) >> 128; |
| 85 |
√ 393
|
⟳ 3
|
if (absTick & 0x400 != 0) price = (price * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; |
| 86 |
√ 3
|
⟳ 3
|
if (absTick & 0x800 != 0) price = (price * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; |
| 87 |
√ 385
|
⟳ 3
|
if (absTick & 0x1000 != 0) price = (price * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; |
| 88 |
√ 385
|
⟳ 3
|
if (absTick & 0x2000 != 0) price = (price * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; |
| 89 |
√ 385
|
⟳ 3
|
if (absTick & 0x4000 != 0) price = (price * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; |
| 90 |
√ 3
|
⟳ 3
|
if (absTick & 0x8000 != 0) price = (price * 0x31be135f97d08fd981231505542fcfa6) >> 128; |
| 91 |
√ 3
|
⟳ 3
|
if (absTick & 0x10000 != 0) price = (price * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; |
| 92 |
√ 3
|
⟳ 3
|
if (absTick & 0x20000 != 0) price = (price * 0x5d6af8dedb81196699c329225ee604) >> 128; |
| 93 |
√ 2841
|
⟳ 3
|
if (absTick & 0x40000 != 0) price = (price * 0x2216e584f5fa1ea926041bedfe98) >> 128; |
| 94 |
√ 3
|
⟳ 3
|
if (absTick & 0x80000 != 0) price = (price * 0x48a170391f7dc42444e8fa2) >> 128; |
| 95 | |||
| 96 |
assembly ("memory-safe") {
|
||
| 97 |
// if (tick > 0) price = type(uint256).max / price; |
||
| 98 |
√ 3
|
⟳ 3
|
if sgt(tick, 0) { price := div(not(0), price) }
|
| 99 | |||
| 100 |
// this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. |
||
| 101 |
// we then downcast because we know the result always fits within 160 bits due to our tick input constraint |
||
| 102 |
// we round up in the division so getTickAtSqrtPrice of the output price is always consistent |
||
| 103 |
// `sub(shl(32, 1), 1)` is `type(uint32).max` |
||
| 104 |
// `price + type(uint32).max` will not overflow because `price` fits in 192 bits |
||
| 105 |
√ 1
|
⟳ 1
|
sqrtPriceX96 := shr(32, add(price, sub(shl(32, 1), 1))) |
| 106 |
} |
||
| 107 |
} |
||
| 108 |
} |
||
| 109 | |||
| 110 |
/// @notice Calculates the greatest tick value such that getPriceAtTick(tick) <= price |
||
| 111 |
/// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getPriceAtTick may |
||
| 112 |
/// ever return. |
||
| 113 |
/// @param sqrtPriceX96 The sqrt price for which to compute the tick as a Q64.96 |
||
| 114 |
/// @return tick The greatest tick for which the price is less than or equal to the input price |
||
| 115 |
√ 1
|
⟳ 1
|
function getTickAtSqrtPrice(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
|
| 116 |
unchecked {
|
||
| 117 |
// Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice(); |
||
| 118 |
// second inequality must be >= because the price can never reach the price at the max tick |
||
| 119 |
// if sqrtPriceX96 < MIN_SQRT_PRICE, the `sub` underflows and `gt` is true |
||
| 120 |
// if sqrtPriceX96 >= MAX_SQRT_PRICE, sqrtPriceX96 - MIN_SQRT_PRICE > MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1 |
||
| 121 |
√ 3
|
⟳ 3
|
if ((sqrtPriceX96 - MIN_SQRT_PRICE) > MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE) {
|
| 122 |
⟳ 2
|
InvalidSqrtPrice.selector.revertWith(sqrtPriceX96); |
|
| 123 |
} |
||
| 124 | |||
| 125 |
√ 1
|
⟳ 1
|
uint256 price = uint256(sqrtPriceX96) << 32; |
| 126 | |||
| 127 |
uint256 r = price; |
||
| 128 |
uint256 msb = 0; |
||
| 129 | |||
| 130 |
assembly ("memory-safe") {
|
||
| 131 |
√ 2
|
⟳ 2
|
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) |
| 132 |
msb := or(msb, f) |
||
| 133 |
√ 3
|
⟳ 3
|
r := shr(f, r) |
| 134 |
} |
||
| 135 |
assembly ("memory-safe") {
|
||
| 136 |
√ 2
|
⟳ 2
|
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) |
| 137 |
√ 2
|
⟳ 2
|
msb := or(msb, f) |
| 138 |
√ 3
|
⟳ 3
|
r := shr(f, r) |
| 139 |
} |
||
| 140 |
assembly ("memory-safe") {
|
||
| 141 |
√ 2
|
⟳ 2
|
let f := shl(5, gt(r, 0xFFFFFFFF)) |
| 142 |
√ 3
|
⟳ 3
|
msb := or(msb, f) |
| 143 |
√ 3
|
⟳ 3
|
r := shr(f, r) |
| 144 |
} |
||
| 145 |
assembly ("memory-safe") {
|
||
| 146 |
√ 2
|
⟳ 2
|
let f := shl(4, gt(r, 0xFFFF)) |
| 147 |
√ 3
|
⟳ 3
|
msb := or(msb, f) |
| 148 |
√ 3
|
⟳ 3
|
r := shr(f, r) |
| 149 |
} |
||
| 150 |
assembly ("memory-safe") {
|
||
| 151 |
√ 2
|
⟳ 2
|
let f := shl(3, gt(r, 0xFF)) |
| 152 |
√ 1
|
⟳ 1
|
msb := or(msb, f) |
| 153 |
√ 3
|
⟳ 3
|
r := shr(f, r) |
| 154 |
} |
||
| 155 |
assembly ("memory-safe") {
|
||
| 156 |
√ 2
|
⟳ 2
|
let f := shl(2, gt(r, 0xF)) |
| 157 |
√ 3
|
⟳ 3
|
msb := or(msb, f) |
| 158 |
√ 3
|
⟳ 3
|
r := shr(f, r) |
| 159 |
} |
||
| 160 |
assembly ("memory-safe") {
|
||
| 161 |
√ 4
|
⟳ 4
|
let f := shl(1, gt(r, 0x3)) |
| 162 |
√ 1
|
⟳ 1
|
msb := or(msb, f) |
| 163 |
√ 4
|
⟳ 4
|
r := shr(f, r) |
| 164 |
} |
||
| 165 |
assembly ("memory-safe") {
|
||
| 166 |
√ 3
|
⟳ 3
|
let f := gt(r, 0x1) |
| 167 |
√ 1
|
⟳ 1
|
msb := or(msb, f) |
| 168 |
} |
||
| 169 | |||
| 170 |
√ 4
|
⟳ 4
|
if (msb >= 128) r = price >> (msb - 127); |
| 171 |
√ 3
|
⟳ 3
|
else r = price << (127 - msb); |
| 172 | |||
| 173 |
√ 2
|
⟳ 2
|
int256 log_2 = (int256(msb) - 128) << 64; |
| 174 | |||
| 175 |
assembly ("memory-safe") {
|
||
| 176 |
√ 5
|
⟳ 5
|
r := shr(127, mul(r, r)) |
| 177 |
√ 4
|
⟳ 4
|
let f := shr(128, r) |
| 178 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(63, f)) |
| 179 |
√ 4
|
⟳ 4
|
r := shr(f, r) |
| 180 |
} |
||
| 181 |
assembly ("memory-safe") {
|
||
| 182 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 183 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 184 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(62, f)) |
| 185 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 186 |
} |
||
| 187 |
assembly ("memory-safe") {
|
||
| 188 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 189 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 190 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(61, f)) |
| 191 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 192 |
} |
||
| 193 |
assembly ("memory-safe") {
|
||
| 194 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 195 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 196 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(60, f)) |
| 197 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 198 |
} |
||
| 199 |
assembly ("memory-safe") {
|
||
| 200 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 201 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 202 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(59, f)) |
| 203 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 204 |
} |
||
| 205 |
assembly ("memory-safe") {
|
||
| 206 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 207 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 208 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(58, f)) |
| 209 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 210 |
} |
||
| 211 |
assembly ("memory-safe") {
|
||
| 212 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 213 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 214 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(57, f)) |
| 215 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 216 |
} |
||
| 217 |
assembly ("memory-safe") {
|
||
| 218 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 219 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 220 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(56, f)) |
| 221 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 222 |
} |
||
| 223 |
assembly ("memory-safe") {
|
||
| 224 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 225 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 226 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(55, f)) |
| 227 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 228 |
} |
||
| 229 |
assembly ("memory-safe") {
|
||
| 230 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 231 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 232 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(54, f)) |
| 233 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 234 |
} |
||
| 235 |
assembly ("memory-safe") {
|
||
| 236 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 237 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 238 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(53, f)) |
| 239 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 240 |
} |
||
| 241 |
assembly ("memory-safe") {
|
||
| 242 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 243 |
√ 3
|
⟳ 3
|
let f := shr(128, r) |
| 244 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(52, f)) |
| 245 |
√ 1
|
⟳ 1
|
r := shr(f, r) |
| 246 |
} |
||
| 247 |
assembly ("memory-safe") {
|
||
| 248 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 249 |
√ 4
|
⟳ 4
|
let f := shr(128, r) |
| 250 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(51, f)) |
| 251 |
√ 4
|
⟳ 4
|
r := shr(f, r) |
| 252 |
} |
||
| 253 |
assembly ("memory-safe") {
|
||
| 254 |
√ 2
|
⟳ 2
|
r := shr(127, mul(r, r)) |
| 255 |
let f := shr(128, r) |
||
| 256 |
√ 7
|
⟳ 7
|
log_2 := or(log_2, shl(50, f)) |
| 257 |
} |
||
| 258 | |||
| 259 |
√ 1
|
⟳ 1
|
int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number |
| 260 | |||
| 261 |
√ 3
|
⟳ 3
|
int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); |
| 262 |
√ 1
|
⟳ 1
|
int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); |
| 263 | |||
| 264 |
√ 15
|
⟳ 15
|
tick = tickLow == tickHi ? tickLow : getSqrtPriceAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; |
| 265 |
} |
||
| 266 |
} |
||
| 267 |
} |
||
| 268 |
| Lines covered: | 0 / 16 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 5 |
import {Currency} from "../types/Currency.sol";
|
||
| 6 |
import {CurrencyReserves} from "./CurrencyReserves.sol";
|
||
| 7 |
import {NonZeroDeltaCount} from "./NonZeroDeltaCount.sol";
|
||
| 8 |
import {Lock} from "./Lock.sol";
|
||
| 9 | |||
| 10 |
/// @notice A helper library to provide state getters that use exttload |
||
| 11 |
library TransientStateLibrary {
|
||
| 12 |
/// @notice returns the reserves for the synced currency |
||
| 13 |
/// @param manager The pool manager contract. |
||
| 14 | |||
| 15 |
/// @return uint256 The reserves of the currency. |
||
| 16 |
/// @dev returns 0 if the reserves are not synced or value is 0. |
||
| 17 |
/// Checks the synced currency to only return valid reserve values (after a sync and before a settle). |
||
| 18 |
function getSyncedReserves(IPoolManager manager) internal view returns (uint256) {
|
||
| 19 |
if (getSyncedCurrency(manager).isZero()) return 0; |
||
| 20 |
return uint256(manager.exttload(CurrencyReserves.RESERVES_OF_SLOT)); |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function getSyncedCurrency(IPoolManager manager) internal view returns (Currency) {
|
||
| 24 |
return Currency.wrap(address(uint160(uint256(manager.exttload(CurrencyReserves.CURRENCY_SLOT))))); |
||
| 25 |
} |
||
| 26 | |||
| 27 |
/// @notice Returns the number of nonzero deltas open on the PoolManager that must be zerod out before the contract is locked |
||
| 28 |
function getNonzeroDeltaCount(IPoolManager manager) internal view returns (uint256) {
|
||
| 29 |
return uint256(manager.exttload(NonZeroDeltaCount.NONZERO_DELTA_COUNT_SLOT)); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
/// @notice Get the current delta for a caller in the given currency |
||
| 33 |
/// @param target The credited account address |
||
| 34 |
/// @param currency The currency for which to lookup the delta |
||
| 35 |
function currencyDelta(IPoolManager manager, address target, Currency currency) internal view returns (int256) {
|
||
| 36 |
bytes32 key; |
||
| 37 |
assembly ("memory-safe") {
|
||
| 38 |
mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff)) |
||
| 39 |
mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) |
||
| 40 |
key := keccak256(0, 64) |
||
| 41 |
} |
||
| 42 |
return int256(uint256(manager.exttload(key))); |
||
| 43 |
} |
||
| 44 | |||
| 45 |
/// @notice Returns whether the contract is unlocked or not |
||
| 46 |
function isUnlocked(IPoolManager manager) internal view returns (bool) {
|
||
| 47 |
return manager.exttload(Lock.IS_UNLOCKED_SLOT) != 0x0; |
||
| 48 |
} |
||
| 49 |
} |
||
| 50 |
| Lines covered: | 1 / 2 (50.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/// @title Math functions that do not check inputs or outputs |
||
| 5 |
/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks |
||
| 6 |
library UnsafeMath {
|
||
| 7 |
/// @notice Returns ceil(x / y) |
||
| 8 |
/// @dev division by 0 has unspecified behavior, and must be checked externally |
||
| 9 |
/// @param x The dividend |
||
| 10 |
/// @param y The divisor |
||
| 11 |
/// @return z The quotient, ceil(x / y) |
||
| 12 |
function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
|
||
| 13 |
unchecked {
|
||
| 14 |
assembly ("memory-safe") {
|
||
| 15 |
√ 10
|
⟳ 10
|
z := add(div(x, y), gt(mod(x, y), 0)) |
| 16 |
} |
||
| 17 |
} |
||
| 18 |
} |
||
| 19 |
} |
||
| 20 |
| Lines covered: | 85 / 148 (57.4%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
|
||
| 7 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 8 | |||
| 9 |
import {Currency} from "../types/Currency.sol";
|
||
| 10 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 11 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 12 |
import {StateLibrary} from "../libraries/StateLibrary.sol";
|
||
| 13 |
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 15 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 16 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 17 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 18 |
import {IActionsHarness} from "../../test/trailofbits/IActionsHarness.sol";
|
||
| 19 | |||
| 20 |
// Supported Actions. |
||
| 21 |
enum Actions {
|
||
| 22 |
SETTLE, |
||
| 23 |
SETTLE_NATIVE, |
||
| 24 |
SETTLE_FOR, |
||
| 25 |
TAKE, |
||
| 26 |
PRANK_TAKE_FROM, |
||
| 27 |
SYNC, |
||
| 28 |
MINT, |
||
| 29 |
BURN, |
||
| 30 |
CLEAR, |
||
| 31 |
ASSERT_BALANCE_EQUALS, |
||
| 32 |
ASSERT_RESERVES_EQUALS, |
||
| 33 |
ASSERT_DELTA_EQUALS, |
||
| 34 |
ASSERT_NONZERO_DELTA_COUNT_EQUALS, |
||
| 35 |
TRANSFER_FROM, |
||
| 36 |
INITIALIZE, |
||
| 37 |
DONATE, |
||
| 38 |
MODIFY_POSITION, |
||
| 39 |
SWAP, |
||
| 40 |
HARNESS_CALLBACK |
||
| 41 |
} |
||
| 42 | |||
| 43 |
/// @notice A router that handles an arbitrary input of actions. |
||
| 44 |
/// TODO: Can continue to add functions per action. |
||
| 45 |
contract ActionsRouter is IUnlockCallback, Test {
|
||
| 46 |
using StateLibrary for IPoolManager; |
||
| 47 |
using TransientStateLibrary for IPoolManager; |
||
| 48 |
using PoolIdLibrary for PoolKey; |
||
| 49 | |||
| 50 |
error ActionNotSupported(); |
||
| 51 | |||
| 52 |
// error thrown so that incorrectly formatted tests don't pass silently |
||
| 53 |
error CheckParameters(); |
||
| 54 | |||
| 55 |
error AssertOnExceptionNotSupported(); |
||
| 56 | |||
| 57 |
IPoolManager manager; |
||
| 58 |
bytes lastReturnData; |
||
| 59 |
√ 8
|
bool assertOnException = false; |
|
| 60 | |||
| 61 |
constructor(IPoolManager _manager) {
|
||
| 62 |
√ 1
|
manager = _manager; |
|
| 63 |
} |
||
| 64 | |||
| 65 |
√ 1
|
⟳ 1
|
function unlockCallback(bytes calldata data) external returns (bytes memory) {
|
| 66 |
√ 3
|
⟳ 3
|
(Actions[] memory actions, bytes[] memory params) = abi.decode(data, (Actions[], bytes[])); |
| 67 |
√ 4
|
⟳ 18
|
if (actions.length != params.length || actions.length == 0) revert CheckParameters(); |
| 68 |
√ 42
|
⟳ 12
|
for (uint256 i = 0; i < actions.length; i++) {
|
| 69 |
√ 39
|
⟳ 12
|
Actions action = actions[i]; |
| 70 |
√ 39
|
⟳ 12
|
bytes memory param = params[i]; |
| 71 |
√ 26
|
⟳ 8
|
if (action == Actions.SETTLE) {
|
| 72 |
√ 1
|
⟳ 1
|
_settle(); |
| 73 |
√ 24
|
⟳ 8
|
} else if (action == Actions.SETTLE_NATIVE) {
|
| 74 |
√ 2
|
⟳ 2
|
_settleNative(param); |
| 75 |
√ 24
|
⟳ 8
|
} else if (action == Actions.SETTLE_FOR) {
|
| 76 |
√ 2
|
⟳ 2
|
_settleFor(param); |
| 77 |
√ 24
|
⟳ 8
|
} else if (action == Actions.TAKE) {
|
| 78 |
√ 2
|
⟳ 2
|
_take(param); |
| 79 |
√ 22
|
⟳ 8
|
} else if (action == Actions.PRANK_TAKE_FROM) {
|
| 80 |
_prankTakeFrom(param); |
||
| 81 |
√ 22
|
⟳ 8
|
} else if (action == Actions.SYNC) {
|
| 82 |
√ 2
|
⟳ 2
|
_sync(param); |
| 83 |
√ 20
|
⟳ 8
|
} else if (action == Actions.MODIFY_POSITION) {
|
| 84 |
√ 2
|
⟳ 2
|
_modify_position(param); |
| 85 |
√ 18
|
⟳ 8
|
} else if (action == Actions.MINT) {
|
| 86 |
√ 2
|
⟳ 2
|
_mint(param); |
| 87 |
√ 18
|
⟳ 8
|
} else if (action == Actions.BURN) {
|
| 88 |
√ 2
|
⟳ 2
|
_burn(param); |
| 89 |
√ 18
|
⟳ 8
|
} else if (action == Actions.CLEAR) {
|
| 90 |
√ 2
|
⟳ 2
|
_clear(param); |
| 91 |
√ 18
|
⟳ 8
|
} else if (action == Actions.ASSERT_BALANCE_EQUALS) {
|
| 92 |
_assertBalanceEquals(param); |
||
| 93 |
√ 18
|
⟳ 8
|
} else if (action == Actions.ASSERT_RESERVES_EQUALS) {
|
| 94 |
_assertReservesEquals(param); |
||
| 95 |
√ 18
|
⟳ 8
|
} else if (action == Actions.ASSERT_DELTA_EQUALS) {
|
| 96 |
_assertDeltaEquals(param); |
||
| 97 |
√ 18
|
⟳ 8
|
} else if (action == Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS) {
|
| 98 |
_assertNonzeroDeltaCountEquals(param); |
||
| 99 |
√ 18
|
⟳ 8
|
} else if (action == Actions.TRANSFER_FROM) {
|
| 100 |
√ 2
|
⟳ 2
|
_transferFrom(param); |
| 101 |
√ 18
|
⟳ 8
|
} else if (action == Actions.INITIALIZE) {
|
| 102 |
_initialize(param); |
||
| 103 |
√ 18
|
⟳ 8
|
} else if (action == Actions.DONATE) {
|
| 104 |
√ 2
|
⟳ 2
|
_donate(param); |
| 105 |
√ 18
|
⟳ 6
|
} else if (action == Actions.SWAP) {
|
| 106 |
√ 2
|
⟳ 2
|
_swap(param); |
| 107 |
√ 18
|
⟳ 6
|
} else if (action == Actions.HARNESS_CALLBACK) {
|
| 108 |
√ 18
|
⟳ 6
|
_harness_callback(param); |
| 109 |
} else {
|
||
| 110 |
assert(false); //todo: remove |
||
| 111 |
revert ActionNotSupported(); |
||
| 112 |
} |
||
| 113 |
√ 13
|
⟳ 3
|
assertOnException = false; |
| 114 |
} |
||
| 115 |
√ 16
|
⟳ 16
|
return ""; |
| 116 |
} |
||
| 117 | |||
| 118 |
function executeActions(Actions[] memory actions, bytes[] memory params) external payable {
|
||
| 119 |
√ 13
|
⟳ 13
|
manager.unlock(abi.encode(actions, params)); |
| 120 |
} |
||
| 121 | |||
| 122 |
/// @notice Set this to "true" to raise an assertion error if the next action reverts. |
||
| 123 |
/// This can be used to create properties that assert that specific actions must never revert, |
||
| 124 |
// however this function should be added to fuzzing blocklists if using multi-abi mode. |
||
| 125 |
function setAssertOnException(bool value) external {
|
||
| 126 |
assertOnException = value; |
||
| 127 |
} |
||
| 128 | |||
| 129 |
function _harness_callback(bytes memory params) internal {
|
||
| 130 |
√ 27
|
⟳ 9
|
(address harness, bytes memory cbParams) = abi.decode(params, (address, bytes)); |
| 131 |
√ 72
|
⟳ 24
|
IActionsHarness(harness).routerCallback(cbParams, lastReturnData); |
| 132 |
√ 45
|
⟳ 10
|
lastReturnData = new bytes(0); // todo: we might need some data smuggled here if harness_callback is the last item in the actions list. |
| 133 |
} |
||
| 134 | |||
| 135 | |||
| 136 |
function _settle() internal {
|
||
| 137 |
√ 11
|
⟳ 11
|
try manager.settle() returns (uint256 paid) {
|
| 138 |
√ 19
|
⟳ 19
|
lastReturnData = abi.encode(paid); |
| 139 |
} catch Error(string memory reason) {
|
||
| 140 |
emit log_named_string("revert reason", reason);
|
||
| 141 |
assertFalse(assertOnException, "_settle reverted, but should not have"); |
||
| 142 |
revert(reason); |
||
| 143 |
} |
||
| 144 |
} |
||
| 145 | |||
| 146 |
function _settleNative(bytes memory params) internal {
|
||
| 147 |
√ 2
|
⟳ 2
|
uint256 amount = abi.decode(params, (uint256)); |
| 148 |
√ 12
|
⟳ 12
|
try manager.settle{value: amount}() returns (uint256 paid) {
|
| 149 |
√ 19
|
⟳ 19
|
lastReturnData = abi.encode(paid); |
| 150 |
} catch Error(string memory reason) {
|
||
| 151 |
emit log_named_string("revert reason", reason);
|
||
| 152 |
assertFalse(assertOnException, "_settleNative reverted, but should not have"); |
||
| 153 |
revert(reason); |
||
| 154 |
} |
||
| 155 |
} |
||
| 156 | |||
| 157 |
function _settleFor(bytes memory params) internal {
|
||
| 158 |
√ 2
|
⟳ 2
|
address recipient = abi.decode(params, (address)); |
| 159 |
√ 11
|
⟳ 11
|
try manager.settleFor(recipient) returns (uint256 paid) {
|
| 160 |
lastReturnData = abi.encode(paid); |
||
| 161 |
} catch Error(string memory reason) {
|
||
| 162 |
emit log_named_string("revert reason", reason);
|
||
| 163 |
assertFalse(assertOnException, "_settleFor reverted, but should not have"); |
||
| 164 |
revert(reason); |
||
| 165 |
} |
||
| 166 |
} |
||
| 167 | |||
| 168 |
function _take(bytes memory params) internal {
|
||
| 169 |
√ 4
|
⟳ 4
|
(Currency currency, address recipient, int128 amount) = abi.decode(params, (Currency, address, int128)); |
| 170 |
√ 10
|
⟳ 10
|
try manager.take(currency, recipient, uint128(amount)) {
|
| 171 |
√ 1
|
⟳ 1
|
lastReturnData = new bytes(0); |
| 172 |
} catch Error(string memory reason) {
|
||
| 173 |
emit log_named_string("revert reason", reason);
|
||
| 174 |
assertFalse(assertOnException, "_take reverted, but should not have"); |
||
| 175 |
revert(reason); |
||
| 176 |
} |
||
| 177 |
} |
||
| 178 | |||
| 179 |
function _prankTakeFrom(bytes memory params) internal {
|
||
| 180 |
if(assertOnException) {
|
||
| 181 |
revert AssertOnExceptionNotSupported(); |
||
| 182 |
} |
||
| 183 |
(Currency currency, address from, address recipient, uint256 amount) = |
||
| 184 |
abi.decode(params, (Currency, address, address, uint256)); |
||
| 185 |
vm.prank(from); |
||
| 186 |
manager.take(currency, recipient, amount); |
||
| 187 |
√ 3
|
⟳ 3
|
lastReturnData = new bytes(0); |
| 188 |
} |
||
| 189 | |||
| 190 |
function _sync(bytes memory params) internal {
|
||
| 191 |
√ 2
|
⟳ 2
|
Currency currency = Currency.wrap(abi.decode(params, (address))); |
| 192 |
√ 11
|
⟳ 11
|
try manager.sync(currency) {
|
| 193 |
√ 1
|
⟳ 1
|
lastReturnData = new bytes(0); |
| 194 |
} catch Error(string memory reason) {
|
||
| 195 |
emit log_named_string("revert eason", reason);
|
||
| 196 |
assertFalse(assertOnException, "_sync reverted, but should not have"); |
||
| 197 |
} |
||
| 198 |
} |
||
| 199 | |||
| 200 |
function _mint(bytes memory params) internal {
|
||
| 201 |
√ 4
|
⟳ 4
|
(address recipient, Currency currency, uint256 amount) = abi.decode(params, (address, Currency, uint256)); |
| 202 |
√ 12
|
⟳ 12
|
try manager.mint(recipient, currency.toId(), amount) {
|
| 203 |
lastReturnData = new bytes(0); |
||
| 204 |
} catch Error(string memory reason) {
|
||
| 205 |
emit log_named_string("revert reason", reason);
|
||
| 206 |
assertFalse(assertOnException, "_mint reverted, but should not have"); |
||
| 207 |
revert(reason); |
||
| 208 |
} |
||
| 209 |
} |
||
| 210 | |||
| 211 |
function _burn(bytes memory params) internal {
|
||
| 212 |
√ 4
|
⟳ 4
|
(address sender, Currency currency, uint256 amount) = abi.decode(params, (address, Currency, uint256)); |
| 213 |
√ 12
|
⟳ 12
|
try manager.burn(sender, currency.toId(), amount){
|
| 214 |
lastReturnData = new bytes(0); |
||
| 215 |
} catch Error(string memory reason) {
|
||
| 216 |
emit log_named_string("revert reason", reason);
|
||
| 217 |
assertFalse(assertOnException, "_burn reverted, but should not have"); |
||
| 218 |
revert(reason); |
||
| 219 |
} |
||
| 220 |
} |
||
| 221 | |||
| 222 |
function _clear(bytes memory params) internal {
|
||
| 223 |
√ 4
|
⟳ 4
|
(Currency currency, uint256 amount, bool measureGas, string memory gasSnapName) = |
| 224 |
√ 1
|
⟳ 1
|
abi.decode(params, (Currency, uint256, bool, string)); |
| 225 |
√ 10
|
⟳ 10
|
try manager.clear(currency, amount) {
|
| 226 |
√ 1
|
⟳ 1
|
lastReturnData = new bytes(0); |
| 227 |
// Disable gas snapshotting b/c echidna/medusa's engines can't handle the cheatcodes. |
||
| 228 |
// if (measureGas) snapLastCall(gasSnapName); |
||
| 229 |
} catch Error(string memory reason) {
|
||
| 230 |
emit log_named_string("revert reason", reason);
|
||
| 231 |
assertFalse(assertOnException, "_clear reverted, but should not have"); |
||
| 232 |
revert(reason); |
||
| 233 |
} |
||
| 234 |
} |
||
| 235 | |||
| 236 |
function _assertBalanceEquals(bytes memory params) internal view {
|
||
| 237 |
if(assertOnException) {
|
||
| 238 |
revert AssertOnExceptionNotSupported(); |
||
| 239 |
} |
||
| 240 |
(Currency currency, address user, uint256 expectedBalance) = abi.decode(params, (Currency, address, uint256)); |
||
| 241 |
assertEq(currency.balanceOf(user), expectedBalance, "usertoken value incorrect"); |
||
| 242 |
} |
||
| 243 | |||
| 244 |
function _assertReservesEquals(bytes memory params) internal view {
|
||
| 245 |
if(assertOnException) {
|
||
| 246 |
revert AssertOnExceptionNotSupported(); |
||
| 247 |
} |
||
| 248 |
uint256 expectedReserves = abi.decode(params, (uint256)); |
||
| 249 |
assertEq(manager.getSyncedReserves(), expectedReserves, "reserves value incorrect"); |
||
| 250 |
} |
||
| 251 | |||
| 252 |
function _assertDeltaEquals(bytes memory params) internal view {
|
||
| 253 |
if(assertOnException) {
|
||
| 254 |
revert AssertOnExceptionNotSupported(); |
||
| 255 |
} |
||
| 256 |
(Currency currency, address caller, int256 expectedDelta) = abi.decode(params, (Currency, address, int256)); |
||
| 257 | |||
| 258 |
assertEq(manager.currencyDelta(caller, currency), expectedDelta, "delta value incorrect"); |
||
| 259 |
} |
||
| 260 | |||
| 261 |
function _assertNonzeroDeltaCountEquals(bytes memory params) internal view {
|
||
| 262 |
if(assertOnException) {
|
||
| 263 |
revert AssertOnExceptionNotSupported(); |
||
| 264 |
} |
||
| 265 |
(uint256 expectedCount) = abi.decode(params, (uint256)); |
||
| 266 |
assertEq(manager.getNonzeroDeltaCount(), expectedCount, "nonzero delta count incorrect"); |
||
| 267 |
} |
||
| 268 | |||
| 269 |
function _transferFrom(bytes memory params) internal {
|
||
| 270 |
√ 4
|
⟳ 4
|
if(assertOnException) {
|
| 271 |
revert AssertOnExceptionNotSupported(); |
||
| 272 |
} |
||
| 273 |
√ 4
|
⟳ 4
|
(Currency currency, address from, address recipient, uint256 amount) = |
| 274 |
√ 1
|
⟳ 1
|
abi.decode(params, (Currency, address, address, uint256)); |
| 275 |
√ 7
|
⟳ 7
|
MockERC20(Currency.unwrap(currency)).transferFrom(from, recipient, uint256(amount)); |
| 276 |
√ 1
|
⟳ 1
|
lastReturnData = new bytes(0); |
| 277 |
} |
||
| 278 | |||
| 279 |
function _initialize(bytes memory params) internal {
|
||
| 280 |
(address token0, address token1, int24 tickSpacing, uint160 initialPrice, uint24 initialFee) = |
||
| 281 |
abi.decode(params, (address, address, int24, uint160, uint24)); |
||
| 282 | |||
| 283 |
PoolKey memory k = PoolKey(Currency.wrap(token0), Currency.wrap(token1), initialFee, tickSpacing, IHooks(address(0))); |
||
| 284 |
|
||
| 285 |
try manager.initialize(k, initialPrice, new bytes(0)) returns (int24 tick ){
|
||
| 286 |
lastReturnData = abi.encode(tick); |
||
| 287 |
return; |
||
| 288 |
} catch Error(string memory reason) {
|
||
| 289 |
emit log_named_string("revert reason", reason);
|
||
| 290 |
assertFalse(assertOnException, "_initialize reverted, but should not have"); |
||
| 291 |
revert(reason); |
||
| 292 |
} |
||
| 293 |
} |
||
| 294 | |||
| 295 |
function _donate(bytes memory params) internal {
|
||
| 296 |
√ 4
|
⟳ 4
|
(PoolKey memory key, uint256 amount0, uint256 amount1) = abi.decode(params, (PoolKey, uint256, uint256)); |
| 297 | |||
| 298 |
√ 8
|
⟳ 8
|
try manager.donate(key, amount0, amount1, new bytes(0)) returns (BalanceDelta delta) {
|
| 299 |
√ 19
|
⟳ 19
|
lastReturnData = abi.encode(delta); |
| 300 |
} catch Error(string memory reason) {
|
||
| 301 |
emit log_named_string("revert reason", reason);
|
||
| 302 |
assertFalse(assertOnException, "_donate reverted, but should not have"); |
||
| 303 |
revert(reason); |
||
| 304 |
} |
||
| 305 |
} |
||
| 306 | |||
| 307 |
function _modify_position(bytes memory params) internal {
|
||
| 308 |
√ 5
|
⟳ 5
|
(PoolKey memory key, int24 tickLower, int24 tickUpper, int128 liquidity, uint256 salt) = |
| 309 |
√ 1
|
⟳ 1
|
abi.decode(params, (PoolKey, int24, int24, int128, uint256)); |
| 310 | |||
| 311 |
√ 46
|
⟳ 46
|
IPoolManager.ModifyLiquidityParams memory modLiqParams = IPoolManager.ModifyLiquidityParams( |
| 312 |
tickLower, |
||
| 313 |
tickUpper, |
||
| 314 |
liquidity, |
||
| 315 |
bytes32(salt)); |
||
| 316 | |||
| 317 |
√ 31
|
⟳ 31
|
try manager.modifyLiquidity(key, modLiqParams, new bytes(0)) returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) {
|
| 318 |
√ 19
|
⟳ 19
|
lastReturnData = abi.encode(callerDelta, feesAccrued); |
| 319 |
} catch Error(string memory reason) {
|
||
| 320 |
emit log_named_string("revert reason", reason);
|
||
| 321 |
assertFalse(assertOnException, "_modify_position reverted, but should not have"); |
||
| 322 |
revert(reason); |
||
| 323 |
} |
||
| 324 | |||
| 325 |
} |
||
| 326 | |||
| 327 |
function _swap(bytes memory params) internal {
|
||
| 328 |
√ 5
|
⟳ 5
|
(bool zeroForOne, int256 amount, PoolKey memory poolKey, uint160 priceLimit) = abi.decode(params, (bool, int256, PoolKey, uint160)); |
| 329 | |||
| 330 |
√ 38
|
⟳ 38
|
IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams( |
| 331 |
zeroForOne, |
||
| 332 |
amount, |
||
| 333 |
priceLimit |
||
| 334 |
); |
||
| 335 | |||
| 336 |
√ 19
|
⟳ 19
|
try manager.swap(poolKey, swapParams, new bytes(0)) returns (BalanceDelta swapDelta) {
|
| 337 |
√ 19
|
⟳ 38
|
lastReturnData = abi.encode(swapDelta); |
| 338 |
} catch Error(string memory reason) {
|
||
| 339 |
emit log_named_string("revert reason", reason);
|
||
| 340 |
assertFalse(assertOnException, "_swap reverted, but should not have"); |
||
| 341 |
revert(reason); |
||
| 342 |
} |
||
| 343 |
} |
||
| 344 | |||
| 345 |
fallback() external payable { }
|
||
| 346 |
receive() external payable { }
|
||
| 347 |
} |
||
| 348 |
| Lines covered: | 0 / 13 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 5 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 6 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 7 |
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
|
||
| 8 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 9 | |||
| 10 |
contract BaseTestHooks is IHooks {
|
||
| 11 |
error HookNotImplemented(); |
||
| 12 | |||
| 13 |
function beforeInitialize( |
||
| 14 |
address, /* sender **/ |
||
| 15 |
PoolKey calldata, /* key **/ |
||
| 16 |
uint160, /* sqrtPriceX96 **/ |
||
| 17 |
bytes calldata /* hookData **/ |
||
| 18 |
) external virtual returns (bytes4) {
|
||
| 19 |
revert HookNotImplemented(); |
||
| 20 |
} |
||
| 21 | |||
| 22 |
function afterInitialize( |
||
| 23 |
address, /* sender **/ |
||
| 24 |
PoolKey calldata, /* key **/ |
||
| 25 |
uint160, /* sqrtPriceX96 **/ |
||
| 26 |
int24, /* tick **/ |
||
| 27 |
bytes calldata /* hookData **/ |
||
| 28 |
) external virtual returns (bytes4) {
|
||
| 29 |
revert HookNotImplemented(); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function beforeAddLiquidity( |
||
| 33 |
address, /* sender **/ |
||
| 34 |
PoolKey calldata, /* key **/ |
||
| 35 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 36 |
bytes calldata /* hookData **/ |
||
| 37 |
) external virtual returns (bytes4) {
|
||
| 38 |
revert HookNotImplemented(); |
||
| 39 |
} |
||
| 40 | |||
| 41 |
function afterAddLiquidity( |
||
| 42 |
address, /* sender **/ |
||
| 43 |
PoolKey calldata, /* key **/ |
||
| 44 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 45 |
BalanceDelta, /* delta **/ |
||
| 46 |
bytes calldata /* hookData **/ |
||
| 47 |
) external virtual returns (bytes4, BalanceDelta) {
|
||
| 48 |
revert HookNotImplemented(); |
||
| 49 |
} |
||
| 50 | |||
| 51 |
function beforeRemoveLiquidity( |
||
| 52 |
address, /* sender **/ |
||
| 53 |
PoolKey calldata, /* key **/ |
||
| 54 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 55 |
bytes calldata /* hookData **/ |
||
| 56 |
) external virtual returns (bytes4) {
|
||
| 57 |
revert HookNotImplemented(); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function afterRemoveLiquidity( |
||
| 61 |
address, /* sender **/ |
||
| 62 |
PoolKey calldata, /* key **/ |
||
| 63 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 64 |
BalanceDelta, /* delta **/ |
||
| 65 |
bytes calldata /* hookData **/ |
||
| 66 |
) external virtual returns (bytes4, BalanceDelta) {
|
||
| 67 |
revert HookNotImplemented(); |
||
| 68 |
} |
||
| 69 | |||
| 70 |
function beforeSwap( |
||
| 71 |
address, /* sender **/ |
||
| 72 |
PoolKey calldata, /* key **/ |
||
| 73 |
IPoolManager.SwapParams calldata, /* params **/ |
||
| 74 |
bytes calldata /* hookData **/ |
||
| 75 |
) external virtual returns (bytes4, BeforeSwapDelta, uint24) {
|
||
| 76 |
revert HookNotImplemented(); |
||
| 77 |
} |
||
| 78 | |||
| 79 |
function afterSwap( |
||
| 80 |
address, /* sender **/ |
||
| 81 |
PoolKey calldata, /* key **/ |
||
| 82 |
IPoolManager.SwapParams calldata, /* params **/ |
||
| 83 |
BalanceDelta, /* delta **/ |
||
| 84 |
bytes calldata /* hookData **/ |
||
| 85 |
) external virtual returns (bytes4, int128) {
|
||
| 86 |
revert HookNotImplemented(); |
||
| 87 |
} |
||
| 88 | |||
| 89 |
function beforeDonate( |
||
| 90 |
address, /* sender **/ |
||
| 91 |
PoolKey calldata, /* key **/ |
||
| 92 |
uint256, /* amount0 **/ |
||
| 93 |
uint256, /* amount1 **/ |
||
| 94 |
bytes calldata /* hookData **/ |
||
| 95 |
) external virtual returns (bytes4) {
|
||
| 96 |
revert HookNotImplemented(); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function afterDonate( |
||
| 100 |
address, /* sender **/ |
||
| 101 |
PoolKey calldata, /* key **/ |
||
| 102 |
uint256, /* amount0 **/ |
||
| 103 |
uint256, /* amount1 **/ |
||
| 104 |
bytes calldata /* hookData **/ |
||
| 105 |
) external virtual returns (bytes4) {
|
||
| 106 |
revert HookNotImplemented(); |
||
| 107 |
} |
||
| 108 |
} |
||
| 109 |
| Lines covered: | 0 / 12 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Currency, CurrencyLibrary} from "../types/Currency.sol";
|
||
| 5 | |||
| 6 |
contract CurrencyTest {
|
||
| 7 |
function transfer(Currency currency, address to, uint256 amount) external {
|
||
| 8 |
currency.transfer(to, amount); |
||
| 9 |
} |
||
| 10 | |||
| 11 |
function balanceOfSelf(Currency currency) external view returns (uint256) {
|
||
| 12 |
return currency.balanceOfSelf(); |
||
| 13 |
} |
||
| 14 | |||
| 15 |
function balanceOf(Currency currency, address owner) external view returns (uint256) {
|
||
| 16 |
return currency.balanceOf(owner); |
||
| 17 |
} |
||
| 18 | |||
| 19 |
function isNative(Currency currency) external pure returns (bool) {
|
||
| 20 |
return currency.isNative(); |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function toId(Currency currency) external pure returns (uint256) {
|
||
| 24 |
return currency.toId(); |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function fromId(uint256 id) external pure returns (Currency) {
|
||
| 28 |
return CurrencyLibrary.fromId(id); |
||
| 29 |
} |
||
| 30 |
} |
||
| 31 |
| Lines covered: | 0 / 13 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 6 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 7 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 8 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 9 |
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
|
||
| 10 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 11 |
import {Currency} from "../types/Currency.sol";
|
||
| 12 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 13 |
import {BaseTestHooks} from "./BaseTestHooks.sol";
|
||
| 14 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 15 |
import {Currency} from "../types/Currency.sol";
|
||
| 16 | |||
| 17 |
contract CustomCurveHook is BaseTestHooks {
|
||
| 18 |
using Hooks for IHooks; |
||
| 19 |
using CurrencySettler for Currency; |
||
| 20 | |||
| 21 |
error AddLiquidityDirectToHook(); |
||
| 22 | |||
| 23 |
IPoolManager immutable manager; |
||
| 24 | |||
| 25 |
constructor(IPoolManager _manager) {
|
||
| 26 |
manager = _manager; |
||
| 27 |
} |
||
| 28 | |||
| 29 |
modifier onlyPoolManager() {
|
||
| 30 |
require(msg.sender == address(manager)); |
||
| 31 |
_; |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function beforeSwap( |
||
| 35 |
address, /* sender **/ |
||
| 36 |
PoolKey calldata key, |
||
| 37 |
IPoolManager.SwapParams calldata params, |
||
| 38 |
bytes calldata /* hookData **/ |
||
| 39 |
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
|
||
| 40 |
(Currency inputCurrency, Currency outputCurrency, uint256 amount) = _getInputOutputAndAmount(key, params); |
||
| 41 | |||
| 42 |
// this "custom curve" is a line, 1-1 |
||
| 43 |
// take the full input amount, and give the full output amount |
||
| 44 |
manager.take(inputCurrency, address(this), amount); |
||
| 45 |
outputCurrency.settle(manager, address(this), amount, false); |
||
| 46 | |||
| 47 |
// return -amountSpecified as specified to no-op the concentrated liquidity swap |
||
| 48 |
BeforeSwapDelta hookDelta = toBeforeSwapDelta(int128(-params.amountSpecified), int128(params.amountSpecified)); |
||
| 49 |
return (IHooks.beforeSwap.selector, hookDelta, 0); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function afterAddLiquidity( |
||
| 53 |
address, /* sender **/ |
||
| 54 |
PoolKey calldata, /* key **/ |
||
| 55 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 56 |
BalanceDelta, /* delta **/ |
||
| 57 |
bytes calldata /* hookData **/ |
||
| 58 |
) external view override onlyPoolManager returns (bytes4, BalanceDelta) {
|
||
| 59 |
revert AddLiquidityDirectToHook(); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function _getInputOutputAndAmount(PoolKey calldata key, IPoolManager.SwapParams calldata params) |
||
| 63 |
internal |
||
| 64 |
pure |
||
| 65 |
returns (Currency input, Currency output, uint256 amount) |
||
| 66 |
{
|
||
| 67 |
(input, output) = params.zeroForOne ? (key.currency0, key.currency1) : (key.currency1, key.currency0); |
||
| 68 | |||
| 69 |
amount = params.amountSpecified < 0 ? uint256(-params.amountSpecified) : uint256(params.amountSpecified); |
||
| 70 |
} |
||
| 71 |
} |
||
| 72 |
| Lines covered: | 0 / 25 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 6 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 7 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 8 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 9 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 10 |
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 11 |
import {Currency} from "../types/Currency.sol";
|
||
| 12 |
import {BaseTestHooks} from "./BaseTestHooks.sol";
|
||
| 13 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 14 |
import {Currency} from "../types/Currency.sol";
|
||
| 15 |
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
|
||
| 16 | |||
| 17 |
contract DeltaReturningHook is BaseTestHooks {
|
||
| 18 |
using Hooks for IHooks; |
||
| 19 |
using CurrencySettler for Currency; |
||
| 20 | |||
| 21 |
IPoolManager immutable manager; |
||
| 22 | |||
| 23 |
int128 deltaSpecified; |
||
| 24 |
int128 deltaUnspecifiedBeforeSwap; |
||
| 25 |
int128 deltaUnspecifiedAfterSwap; |
||
| 26 | |||
| 27 |
constructor(IPoolManager _manager) {
|
||
| 28 |
manager = _manager; |
||
| 29 |
} |
||
| 30 | |||
| 31 |
modifier onlyPoolManager() {
|
||
| 32 |
require(msg.sender == address(manager)); |
||
| 33 |
_; |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function setDeltaSpecified(int128 delta) external {
|
||
| 37 |
deltaSpecified = delta; |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function setDeltaUnspecifiedBeforeSwap(int128 delta) external {
|
||
| 41 |
deltaUnspecifiedBeforeSwap = delta; |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function setDeltaUnspecifiedAfterSwap(int128 delta) external {
|
||
| 45 |
deltaUnspecifiedAfterSwap = delta; |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function beforeSwap( |
||
| 49 |
address, /* sender **/ |
||
| 50 |
PoolKey calldata key, |
||
| 51 |
IPoolManager.SwapParams calldata params, |
||
| 52 |
bytes calldata /* hookData **/ |
||
| 53 |
) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
|
||
| 54 |
(Currency specifiedCurrency, Currency unspecifiedCurrency) = _sortCurrencies(key, params); |
||
| 55 | |||
| 56 |
if (deltaSpecified != 0) _settleOrTake(specifiedCurrency, deltaSpecified); |
||
| 57 |
if (deltaUnspecifiedBeforeSwap != 0) _settleOrTake(unspecifiedCurrency, deltaUnspecifiedBeforeSwap); |
||
| 58 | |||
| 59 |
BeforeSwapDelta beforeSwapDelta = toBeforeSwapDelta(deltaSpecified, deltaUnspecifiedBeforeSwap); |
||
| 60 | |||
| 61 |
return (IHooks.beforeSwap.selector, beforeSwapDelta, 0); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function afterSwap( |
||
| 65 |
address, /* sender **/ |
||
| 66 |
PoolKey calldata key, |
||
| 67 |
IPoolManager.SwapParams calldata params, |
||
| 68 |
BalanceDelta, /* delta **/ |
||
| 69 |
bytes calldata /* hookData **/ |
||
| 70 |
) external override onlyPoolManager returns (bytes4, int128) {
|
||
| 71 |
(, Currency unspecifiedCurrency) = _sortCurrencies(key, params); |
||
| 72 |
_settleOrTake(unspecifiedCurrency, deltaUnspecifiedAfterSwap); |
||
| 73 | |||
| 74 |
return (IHooks.afterSwap.selector, deltaUnspecifiedAfterSwap); |
||
| 75 |
} |
||
| 76 | |||
| 77 |
function _sortCurrencies(PoolKey calldata key, IPoolManager.SwapParams calldata params) |
||
| 78 |
internal |
||
| 79 |
pure |
||
| 80 |
returns (Currency specified, Currency unspecified) |
||
| 81 |
{
|
||
| 82 |
(specified, unspecified) = (params.zeroForOne == (params.amountSpecified < 0)) |
||
| 83 |
? (key.currency0, key.currency1) |
||
| 84 |
: (key.currency1, key.currency0); |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function _settleOrTake(Currency currency, int128 delta) internal {
|
||
| 88 |
// positive amount means positive delta for the hook, so it can take |
||
| 89 |
// negative it should settle |
||
| 90 |
if (delta > 0) {
|
||
| 91 |
currency.take(manager, address(this), uint128(delta), false); |
||
| 92 |
} else {
|
||
| 93 |
uint256 amount = uint256(-int256(delta)); |
||
| 94 |
if (currency.isNative()) {
|
||
| 95 |
manager.settle{value: amount}();
|
||
| 96 |
} else {
|
||
| 97 |
currency.settle(manager, address(this), amount, false); |
||
| 98 |
} |
||
| 99 |
} |
||
| 100 |
} |
||
| 101 |
} |
||
| 102 |
| Lines covered: | 0 / 10 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {BaseTestHooks} from "./BaseTestHooks.sol";
|
||
| 5 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 6 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 7 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 8 |
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
|
||
| 9 |
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
|
||
| 10 | |||
| 11 |
contract DynamicFeesTestHook is BaseTestHooks {
|
||
| 12 |
uint24 internal fee; |
||
| 13 |
IPoolManager manager; |
||
| 14 | |||
| 15 |
function setManager(IPoolManager _manager) external {
|
||
| 16 |
manager = _manager; |
||
| 17 |
} |
||
| 18 | |||
| 19 |
function setFee(uint24 _fee) external {
|
||
| 20 |
fee = _fee; |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function afterInitialize(address, PoolKey calldata key, uint160, int24, bytes calldata) |
||
| 24 |
external |
||
| 25 |
override |
||
| 26 |
returns (bytes4) |
||
| 27 |
{
|
||
| 28 |
manager.updateDynamicLPFee(key, fee); |
||
| 29 |
return IHooks.afterInitialize.selector; |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata, bytes calldata) |
||
| 33 |
external |
||
| 34 |
override |
||
| 35 |
returns (bytes4, BeforeSwapDelta, uint24) |
||
| 36 |
{
|
||
| 37 |
manager.updateDynamicLPFee(key, fee); |
||
| 38 |
return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0); |
||
| 39 |
} |
||
| 40 | |||
| 41 |
function forcePoolFeeUpdate(PoolKey calldata _key, uint24 _fee) external {
|
||
| 42 |
manager.updateDynamicLPFee(_key, _fee); |
||
| 43 |
} |
||
| 44 |
} |
||
| 45 |
| Lines covered: | 0 / 6 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {BaseTestHooks} from "./BaseTestHooks.sol";
|
||
| 5 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 6 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 7 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 8 |
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
|
||
| 9 |
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
|
||
| 10 | |||
| 11 |
contract DynamicReturnFeeTestHook is BaseTestHooks {
|
||
| 12 |
using LPFeeLibrary for uint24; |
||
| 13 | |||
| 14 |
uint24 internal fee; |
||
| 15 |
IPoolManager manager; |
||
| 16 | |||
| 17 |
function setManager(IPoolManager _manager) external {
|
||
| 18 |
manager = _manager; |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function setFee(uint24 _fee) external {
|
||
| 22 |
fee = _fee; |
||
| 23 |
} |
||
| 24 | |||
| 25 |
function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata) |
||
| 26 |
external |
||
| 27 |
view |
||
| 28 |
override |
||
| 29 |
returns (bytes4, BeforeSwapDelta, uint24) |
||
| 30 |
{
|
||
| 31 |
// attach the fee flag to `fee` to enable overriding the pool's stored fee |
||
| 32 |
return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, fee | LPFeeLibrary.OVERRIDE_FEE_FLAG); |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function forcePoolFeeUpdate(PoolKey calldata _key, uint24 _fee) external {
|
||
| 36 |
manager.updateDynamicLPFee(_key, _fee); |
||
| 37 |
} |
||
| 38 |
} |
||
| 39 |
| Lines covered: | 0 / 2 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
contract EmptyRevertContract {
|
||
| 5 |
// a contract to simulate reverting with no returndata, to test that our error catching works |
||
| 6 |
fallback() external {
|
||
| 7 |
revert(); |
||
| 8 |
} |
||
| 9 |
} |
||
| 10 |
| Lines covered: | 0 / 16 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 6 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 9 |
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
|
||
| 10 | |||
| 11 |
contract EmptyTestHooks is IHooks {
|
||
| 12 |
using Hooks for IHooks; |
||
| 13 | |||
| 14 |
constructor() {
|
||
| 15 |
IHooks(this).validateHookPermissions( |
||
| 16 |
Hooks.Permissions({
|
||
| 17 |
beforeInitialize: true, |
||
| 18 |
afterInitialize: true, |
||
| 19 |
beforeAddLiquidity: true, |
||
| 20 |
afterAddLiquidity: true, |
||
| 21 |
beforeRemoveLiquidity: true, |
||
| 22 |
afterRemoveLiquidity: true, |
||
| 23 |
beforeSwap: true, |
||
| 24 |
afterSwap: true, |
||
| 25 |
beforeDonate: true, |
||
| 26 |
afterDonate: true, |
||
| 27 |
beforeSwapReturnDelta: true, |
||
| 28 |
afterSwapReturnDelta: true, |
||
| 29 |
afterAddLiquidityReturnDelta: true, |
||
| 30 |
afterRemoveLiquidityReturnDelta: true |
||
| 31 |
}) |
||
| 32 |
); |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function beforeInitialize(address, PoolKey calldata, uint160, bytes calldata) |
||
| 36 |
external |
||
| 37 |
pure |
||
| 38 |
override |
||
| 39 |
returns (bytes4) |
||
| 40 |
{
|
||
| 41 |
return IHooks.beforeInitialize.selector; |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function afterInitialize(address, PoolKey calldata, uint160, int24, bytes calldata) |
||
| 45 |
external |
||
| 46 |
pure |
||
| 47 |
override |
||
| 48 |
returns (bytes4) |
||
| 49 |
{
|
||
| 50 |
return IHooks.afterInitialize.selector; |
||
| 51 |
} |
||
| 52 | |||
| 53 |
function beforeAddLiquidity(address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, bytes calldata) |
||
| 54 |
external |
||
| 55 |
pure |
||
| 56 |
override |
||
| 57 |
returns (bytes4) |
||
| 58 |
{
|
||
| 59 |
return IHooks.beforeAddLiquidity.selector; |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function afterAddLiquidity( |
||
| 63 |
address, |
||
| 64 |
PoolKey calldata, |
||
| 65 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 66 |
BalanceDelta, |
||
| 67 |
bytes calldata |
||
| 68 |
) external pure override returns (bytes4, BalanceDelta) {
|
||
| 69 |
return (IHooks.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function beforeRemoveLiquidity( |
||
| 73 |
address, |
||
| 74 |
PoolKey calldata, |
||
| 75 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 76 |
bytes calldata |
||
| 77 |
) external pure override returns (bytes4) {
|
||
| 78 |
return IHooks.beforeRemoveLiquidity.selector; |
||
| 79 |
} |
||
| 80 | |||
| 81 |
function afterRemoveLiquidity( |
||
| 82 |
address, |
||
| 83 |
PoolKey calldata, |
||
| 84 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 85 |
BalanceDelta, |
||
| 86 |
bytes calldata |
||
| 87 |
) external pure override returns (bytes4, BalanceDelta) {
|
||
| 88 |
return (IHooks.afterRemoveLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA); |
||
| 89 |
} |
||
| 90 | |||
| 91 |
function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata) |
||
| 92 |
external |
||
| 93 |
pure |
||
| 94 |
override |
||
| 95 |
returns (bytes4, BeforeSwapDelta, uint24) |
||
| 96 |
{
|
||
| 97 |
return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0); |
||
| 98 |
} |
||
| 99 | |||
| 100 |
function afterSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, BalanceDelta, bytes calldata) |
||
| 101 |
external |
||
| 102 |
pure |
||
| 103 |
override |
||
| 104 |
returns (bytes4, int128) |
||
| 105 |
{
|
||
| 106 |
return (IHooks.afterSwap.selector, 0); |
||
| 107 |
} |
||
| 108 | |||
| 109 |
function beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) |
||
| 110 |
external |
||
| 111 |
pure |
||
| 112 |
override |
||
| 113 |
returns (bytes4) |
||
| 114 |
{
|
||
| 115 |
return IHooks.beforeDonate.selector; |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) |
||
| 119 |
external |
||
| 120 |
pure |
||
| 121 |
override |
||
| 122 |
returns (bytes4) |
||
| 123 |
{
|
||
| 124 |
return IHooks.afterDonate.selector; |
||
| 125 |
} |
||
| 126 |
} |
||
| 127 |
| Lines covered: | 0 / 27 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 6 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 7 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 8 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 9 |
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 10 |
import {Currency} from "../types/Currency.sol";
|
||
| 11 |
import {BaseTestHooks} from "./BaseTestHooks.sol";
|
||
| 12 | |||
| 13 |
contract FeeTakingHook is BaseTestHooks {
|
||
| 14 |
using Hooks for IHooks; |
||
| 15 |
using SafeCast for uint256; |
||
| 16 |
using SafeCast for int128; |
||
| 17 | |||
| 18 |
IPoolManager immutable manager; |
||
| 19 | |||
| 20 |
constructor(IPoolManager _manager) {
|
||
| 21 |
manager = _manager; |
||
| 22 |
} |
||
| 23 | |||
| 24 |
modifier onlyPoolManager() {
|
||
| 25 |
require(msg.sender == address(manager)); |
||
| 26 |
_; |
||
| 27 |
} |
||
| 28 | |||
| 29 |
uint128 public constant LIQUIDITY_FEE = 543; // 543/10000 = 5.43% |
||
| 30 |
uint128 public constant SWAP_FEE_BIPS = 123; // 123/10000 = 1.23% |
||
| 31 |
uint128 public constant TOTAL_BIPS = 10000; |
||
| 32 | |||
| 33 |
function afterSwap( |
||
| 34 |
address, /* sender **/ |
||
| 35 |
PoolKey calldata key, |
||
| 36 |
IPoolManager.SwapParams calldata params, |
||
| 37 |
BalanceDelta delta, |
||
| 38 |
bytes calldata /* hookData **/ |
||
| 39 |
) external override onlyPoolManager returns (bytes4, int128) {
|
||
| 40 |
// fee will be in the unspecified token of the swap |
||
| 41 |
bool specifiedTokenIs0 = (params.amountSpecified < 0 == params.zeroForOne); |
||
| 42 |
(Currency feeCurrency, int128 swapAmount) = |
||
| 43 |
(specifiedTokenIs0) ? (key.currency1, delta.amount1()) : (key.currency0, delta.amount0()); |
||
| 44 |
// if fee is on output, get the absolute output amount |
||
| 45 |
if (swapAmount < 0) swapAmount = -swapAmount; |
||
| 46 | |||
| 47 |
uint256 feeAmount = uint128(swapAmount) * SWAP_FEE_BIPS / TOTAL_BIPS; |
||
| 48 |
manager.take(feeCurrency, address(this), feeAmount); |
||
| 49 | |||
| 50 |
return (IHooks.afterSwap.selector, feeAmount.toInt128()); |
||
| 51 |
} |
||
| 52 | |||
| 53 |
function afterRemoveLiquidity( |
||
| 54 |
address, /* sender **/ |
||
| 55 |
PoolKey calldata key, |
||
| 56 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 57 |
BalanceDelta delta, |
||
| 58 |
bytes calldata /* hookData **/ |
||
| 59 |
) external override onlyPoolManager returns (bytes4, BalanceDelta) {
|
||
| 60 |
assert(delta.amount0() >= 0 && delta.amount1() >= 0); |
||
| 61 | |||
| 62 |
uint128 feeAmount0 = uint128(delta.amount0()) * LIQUIDITY_FEE / TOTAL_BIPS; |
||
| 63 |
uint128 feeAmount1 = uint128(delta.amount1()) * LIQUIDITY_FEE / TOTAL_BIPS; |
||
| 64 | |||
| 65 |
manager.take(key.currency0, address(this), feeAmount0); |
||
| 66 |
manager.take(key.currency1, address(this), feeAmount1); |
||
| 67 | |||
| 68 |
return (IHooks.afterRemoveLiquidity.selector, toBalanceDelta(int128(feeAmount0), int128(feeAmount1))); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
function afterAddLiquidity( |
||
| 72 |
address, /* sender **/ |
||
| 73 |
PoolKey calldata key, |
||
| 74 |
IPoolManager.ModifyLiquidityParams calldata, /* params **/ |
||
| 75 |
BalanceDelta delta, |
||
| 76 |
bytes calldata /* hookData **/ |
||
| 77 |
) external override onlyPoolManager returns (bytes4, BalanceDelta) {
|
||
| 78 |
assert(delta.amount0() <= 0 && delta.amount1() <= 0); |
||
| 79 | |||
| 80 |
uint128 feeAmount0 = uint128(-delta.amount0()) * LIQUIDITY_FEE / TOTAL_BIPS; |
||
| 81 |
uint128 feeAmount1 = uint128(-delta.amount1()) * LIQUIDITY_FEE / TOTAL_BIPS; |
||
| 82 | |||
| 83 |
manager.take(key.currency0, address(this), feeAmount0); |
||
| 84 |
manager.take(key.currency1, address(this), feeAmount1); |
||
| 85 | |||
| 86 |
return (IHooks.afterAddLiquidity.selector, toBalanceDelta(int128(feeAmount0), int128(feeAmount1))); |
||
| 87 |
} |
||
| 88 |
} |
||
| 89 |
| Lines covered: | 0 / 62 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 5 |
import {StdUtils} from "forge-std/StdUtils.sol";
|
||
| 6 | |||
| 7 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 8 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 9 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 10 |
import {TickMath} from "../libraries/TickMath.sol";
|
||
| 11 |
import {Pool} from "../libraries/Pool.sol";
|
||
| 12 |
import {PoolModifyLiquidityTest} from "./PoolModifyLiquidityTest.sol";
|
||
| 13 |
import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol";
|
||
| 14 |
import {SafeCast} from "../../src/libraries/SafeCast.sol";
|
||
| 15 | |||
| 16 |
contract Fuzzers is StdUtils {
|
||
| 17 |
using SafeCast for uint256; |
||
| 18 | |||
| 19 |
Vm internal constant _vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
|
||
| 20 | |||
| 21 |
function boundLiquidityDelta(PoolKey memory key, int256 liquidityDeltaUnbounded, int256 liquidityMaxByAmount) |
||
| 22 |
internal |
||
| 23 |
pure |
||
| 24 |
returns (int256) |
||
| 25 |
{
|
||
| 26 |
int256 liquidityMaxPerTick = int256(uint256(Pool.tickSpacingToMaxLiquidityPerTick(key.tickSpacing))); |
||
| 27 | |||
| 28 |
// Finally bound the seeded liquidity by either the max per tick, or by the amount allowed in the position range. |
||
| 29 |
int256 liquidityMax = liquidityMaxByAmount > liquidityMaxPerTick ? liquidityMaxPerTick : liquidityMaxByAmount; |
||
| 30 |
_vm.assume(liquidityMax != 0); |
||
| 31 |
return bound(liquidityDeltaUnbounded, 1, liquidityMax); |
||
| 32 |
} |
||
| 33 | |||
| 34 |
// Uses tickSpacingToMaxLiquidityPerTick/2 as one of the possible bounds. |
||
| 35 |
// Potentially adjust this value to be more strict for positions that touch the same tick. |
||
| 36 |
function boundLiquidityDeltaTightly( |
||
| 37 |
PoolKey memory key, |
||
| 38 |
int256 liquidityDeltaUnbounded, |
||
| 39 |
int256 liquidityMaxByAmount, |
||
| 40 |
uint256 maxPositions |
||
| 41 |
) internal pure returns (int256) {
|
||
| 42 |
// Divide by half to bound liquidity more. TODO: Probably a better way to do this. |
||
| 43 |
int256 liquidityMaxTightBound = |
||
| 44 |
int256(uint256(Pool.tickSpacingToMaxLiquidityPerTick(key.tickSpacing)) / maxPositions); |
||
| 45 | |||
| 46 |
// Finally bound the seeded liquidity by either the max per tick, or by the amount allowed in the position range. |
||
| 47 |
int256 liquidityMax = |
||
| 48 |
liquidityMaxByAmount > liquidityMaxTightBound ? liquidityMaxTightBound : liquidityMaxByAmount; |
||
| 49 |
_vm.assume(liquidityMax != 0); |
||
| 50 |
return bound(liquidityDeltaUnbounded, 1, liquidityMax); |
||
| 51 |
} |
||
| 52 | |||
| 53 |
function getLiquidityDeltaFromAmounts(int24 tickLower, int24 tickUpper, uint160 sqrtPriceX96) |
||
| 54 |
internal |
||
| 55 |
pure |
||
| 56 |
returns (int256) |
||
| 57 |
{
|
||
| 58 |
// First get the maximum amount0 and maximum amount1 that can be deposited at this range. |
||
| 59 |
(uint256 maxAmount0, uint256 maxAmount1) = LiquidityAmounts.getAmountsForLiquidity( |
||
| 60 |
sqrtPriceX96, |
||
| 61 |
TickMath.getSqrtPriceAtTick(tickLower), |
||
| 62 |
TickMath.getSqrtPriceAtTick(tickUpper), |
||
| 63 |
uint128(type(int128).max) |
||
| 64 |
); |
||
| 65 | |||
| 66 |
// Compare the max amounts (defined by the range of the position) to the max amount constrained by the type container. |
||
| 67 |
// The true maximum should be the minimum of the two. |
||
| 68 |
// (ie If the position range allows a deposit of more then int128.max in any token, then here we cap it at int128.max.) |
||
| 69 | |||
| 70 |
uint256 amount0 = uint256(type(uint128).max / 2); |
||
| 71 |
uint256 amount1 = uint256(type(uint128).max / 2); |
||
| 72 | |||
| 73 |
maxAmount0 = maxAmount0 > amount0 ? amount0 : maxAmount0; |
||
| 74 |
maxAmount1 = maxAmount1 > amount1 ? amount1 : maxAmount1; |
||
| 75 | |||
| 76 |
int256 liquidityMaxByAmount = uint256( |
||
| 77 |
LiquidityAmounts.getLiquidityForAmounts( |
||
| 78 |
sqrtPriceX96, |
||
| 79 |
TickMath.getSqrtPriceAtTick(tickLower), |
||
| 80 |
TickMath.getSqrtPriceAtTick(tickUpper), |
||
| 81 |
maxAmount0, |
||
| 82 |
maxAmount1 |
||
| 83 |
) |
||
| 84 |
).toInt256(); |
||
| 85 | |||
| 86 |
return liquidityMaxByAmount; |
||
| 87 |
} |
||
| 88 | |||
| 89 |
function boundTicks(int24 tickLower, int24 tickUpper, int24 tickSpacing) internal pure returns (int24, int24) {
|
||
| 90 |
tickLower = int24( |
||
| 91 |
bound( |
||
| 92 |
int256(tickLower), |
||
| 93 |
int256(TickMath.minUsableTick(tickSpacing)), |
||
| 94 |
int256(TickMath.maxUsableTick(tickSpacing)) |
||
| 95 |
) |
||
| 96 |
); |
||
| 97 |
tickUpper = int24( |
||
| 98 |
bound( |
||
| 99 |
int256(tickUpper), |
||
| 100 |
int256(TickMath.minUsableTick(tickSpacing)), |
||
| 101 |
int256(TickMath.maxUsableTick(tickSpacing)) |
||
| 102 |
) |
||
| 103 |
); |
||
| 104 | |||
| 105 |
// round down ticks |
||
| 106 |
tickLower = (tickLower / tickSpacing) * tickSpacing; |
||
| 107 |
tickUpper = (tickUpper / tickSpacing) * tickSpacing; |
||
| 108 | |||
| 109 |
(tickLower, tickUpper) = tickLower < tickUpper ? (tickLower, tickUpper) : (tickUpper, tickLower); |
||
| 110 | |||
| 111 |
if (tickLower == tickUpper) {
|
||
| 112 |
if (tickLower != TickMath.minUsableTick(tickSpacing)) tickLower = tickLower - tickSpacing; |
||
| 113 |
else tickUpper = tickUpper + tickSpacing; |
||
| 114 |
} |
||
| 115 | |||
| 116 |
return (tickLower, tickUpper); |
||
| 117 |
} |
||
| 118 | |||
| 119 |
function boundTicks(PoolKey memory key, int24 tickLower, int24 tickUpper) internal pure returns (int24, int24) {
|
||
| 120 |
return boundTicks(tickLower, tickUpper, key.tickSpacing); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function createRandomSqrtPriceX96(int24 tickSpacing, int256 seed) internal pure returns (uint160) {
|
||
| 124 |
int256 min = int256(TickMath.minUsableTick(tickSpacing)); |
||
| 125 |
int256 max = int256(TickMath.maxUsableTick(tickSpacing)); |
||
| 126 |
int256 randomTick = bound(seed, min + 1, max - 1); |
||
| 127 |
return TickMath.getSqrtPriceAtTick(int24(randomTick)); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
/// @dev Obtain fuzzed and bounded parameters for creating liquidity |
||
| 131 |
/// @param key The pool key |
||
| 132 |
/// @param params IPoolManager.ModifyLiquidityParams Note that these parameters are unbounded |
||
| 133 |
/// @param sqrtPriceX96 The current sqrt price |
||
| 134 |
function createFuzzyLiquidityParams( |
||
| 135 |
PoolKey memory key, |
||
| 136 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 137 |
uint160 sqrtPriceX96 |
||
| 138 |
) internal pure returns (IPoolManager.ModifyLiquidityParams memory result) {
|
||
| 139 |
(result.tickLower, result.tickUpper) = boundTicks(key, params.tickLower, params.tickUpper); |
||
| 140 |
int256 liquidityDeltaFromAmounts = |
||
| 141 |
getLiquidityDeltaFromAmounts(result.tickLower, result.tickUpper, sqrtPriceX96); |
||
| 142 |
result.liquidityDelta = boundLiquidityDelta(key, params.liquidityDelta, liquidityDeltaFromAmounts); |
||
| 143 |
} |
||
| 144 | |||
| 145 |
// Creates liquidity parameters with a stricter bound. Should be used if multiple positions being intitialized on the pool, with potential for tick overlap. |
||
| 146 |
function createFuzzyLiquidityParamsWithTightBound( |
||
| 147 |
PoolKey memory key, |
||
| 148 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 149 |
uint160 sqrtPriceX96, |
||
| 150 |
uint256 maxPositions |
||
| 151 |
) internal pure returns (IPoolManager.ModifyLiquidityParams memory result) {
|
||
| 152 |
(result.tickLower, result.tickUpper) = boundTicks(key, params.tickLower, params.tickUpper); |
||
| 153 |
int256 liquidityDeltaFromAmounts = |
||
| 154 |
getLiquidityDeltaFromAmounts(result.tickLower, result.tickUpper, sqrtPriceX96); |
||
| 155 | |||
| 156 |
result.liquidityDelta = |
||
| 157 |
boundLiquidityDeltaTightly(key, params.liquidityDelta, liquidityDeltaFromAmounts, maxPositions); |
||
| 158 |
} |
||
| 159 | |||
| 160 |
function createFuzzyLiquidity( |
||
| 161 |
PoolModifyLiquidityTest modifyLiquidityRouter, |
||
| 162 |
PoolKey memory key, |
||
| 163 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 164 |
uint160 sqrtPriceX96, |
||
| 165 |
bytes memory hookData |
||
| 166 |
) internal returns (IPoolManager.ModifyLiquidityParams memory result, BalanceDelta delta) {
|
||
| 167 |
result = createFuzzyLiquidityParams(key, params, sqrtPriceX96); |
||
| 168 |
delta = modifyLiquidityRouter.modifyLiquidity(key, result, hookData); |
||
| 169 |
} |
||
| 170 | |||
| 171 |
// There exists possible positions in the pool, so we tighten the boundaries of liquidity. |
||
| 172 |
function createFuzzyLiquidityWithTightBound( |
||
| 173 |
PoolModifyLiquidityTest modifyLiquidityRouter, |
||
| 174 |
PoolKey memory key, |
||
| 175 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 176 |
uint160 sqrtPriceX96, |
||
| 177 |
bytes memory hookData, |
||
| 178 |
uint256 maxPositions |
||
| 179 |
) internal returns (IPoolManager.ModifyLiquidityParams memory result, BalanceDelta delta) {
|
||
| 180 |
result = createFuzzyLiquidityParamsWithTightBound(key, params, sqrtPriceX96, maxPositions); |
||
| 181 |
delta = modifyLiquidityRouter.modifyLiquidity(key, result, hookData); |
||
| 182 |
} |
||
| 183 |
} |
||
| 184 |
| Lines covered: | 0 / 31 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 6 | |||
| 7 |
contract HooksTest {
|
||
| 8 |
using Hooks for IHooks; |
||
| 9 | |||
| 10 |
function validateHookPermissions(address hookAddress, Hooks.Permissions calldata params) external pure {
|
||
| 11 |
IHooks(hookAddress).validateHookPermissions(params); |
||
| 12 |
} |
||
| 13 | |||
| 14 |
function isValidHookAddress(address hookAddress, uint24 fee) external pure returns (bool) {
|
||
| 15 |
return IHooks(hookAddress).isValidHookAddress(fee); |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function shouldCallBeforeInitialize(address hookAddress) external pure returns (bool) {
|
||
| 19 |
return IHooks(hookAddress).hasPermission(Hooks.BEFORE_INITIALIZE_FLAG); |
||
| 20 |
} |
||
| 21 | |||
| 22 |
function shouldCallAfterInitialize(address hookAddress) external pure returns (bool) {
|
||
| 23 |
return IHooks(hookAddress).hasPermission(Hooks.AFTER_INITIALIZE_FLAG); |
||
| 24 |
} |
||
| 25 | |||
| 26 |
function shouldCallBeforeSwap(address hookAddress) external pure returns (bool) {
|
||
| 27 |
return IHooks(hookAddress).hasPermission(Hooks.BEFORE_SWAP_FLAG); |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function shouldCallAfterSwap(address hookAddress) external pure returns (bool) {
|
||
| 31 |
return IHooks(hookAddress).hasPermission(Hooks.AFTER_SWAP_FLAG); |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function shouldCallBeforeAddLiquidity(address hookAddress) external pure returns (bool) {
|
||
| 35 |
return IHooks(hookAddress).hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function shouldCallAfterAddLiquidity(address hookAddress) external pure returns (bool) {
|
||
| 39 |
return IHooks(hookAddress).hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG); |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function shouldCallBeforeRemoveLiquidity(address hookAddress) external pure returns (bool) {
|
||
| 43 |
return IHooks(hookAddress).hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function shouldCallAfterRemoveLiquidity(address hookAddress) external pure returns (bool) {
|
||
| 47 |
return IHooks(hookAddress).hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG); |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function shouldCallBeforeDonate(address hookAddress) external pure returns (bool) {
|
||
| 51 |
return IHooks(hookAddress).hasPermission(Hooks.BEFORE_DONATE_FLAG); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
function shouldCallAfterDonate(address hookAddress) external pure returns (bool) {
|
||
| 55 |
return IHooks(hookAddress).hasPermission(Hooks.AFTER_DONATE_FLAG); |
||
| 56 |
} |
||
| 57 | |||
| 58 |
function getGasCostOfShouldCall(address hookAddress) external view returns (uint256) {
|
||
| 59 |
uint256 gasBefore = gasleft(); |
||
| 60 |
IHooks(hookAddress).hasPermission(Hooks.BEFORE_SWAP_FLAG); |
||
| 61 |
return gasBefore - gasleft(); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function getGasCostOfValidateHookAddress(address hookAddress, Hooks.Permissions calldata params) |
||
| 65 |
external |
||
| 66 |
view |
||
| 67 |
returns (uint256) |
||
| 68 |
{
|
||
| 69 |
uint256 gasBefore = gasleft(); |
||
| 70 |
IHooks(hookAddress).validateHookPermissions(params); |
||
| 71 |
return gasBefore - gasleft(); |
||
| 72 |
} |
||
| 73 |
} |
||
| 74 |
| Lines covered: | 0 / 3 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {LiquidityMath} from "../libraries/LiquidityMath.sol";
|
||
| 5 | |||
| 6 |
contract LiquidityMathTest {
|
||
| 7 |
function addDelta(uint128 x, int128 y) external pure returns (uint128 z) {
|
||
| 8 |
return LiquidityMath.addDelta(x, y); |
||
| 9 |
} |
||
| 10 |
} |
||
| 11 |
| Lines covered: | 0 / 15 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol";
|
||
| 5 | |||
| 6 |
/// @notice Mock contract that tracks the number of calls to various functions by selector |
||
| 7 |
/// @dev allows for proxying to an implementation contract |
||
| 8 |
/// if real logic or return values are needed |
||
| 9 |
contract MockContract is Proxy {
|
||
| 10 |
mapping(bytes32 => uint256) public calls; |
||
| 11 |
mapping(bytes32 => mapping(bytes => uint256)) public callParams; |
||
| 12 | |||
| 13 |
/// @notice If set, delegatecall to implementation after tracking call |
||
| 14 |
address internal impl; |
||
| 15 | |||
| 16 |
function timesCalledSelector(bytes32 selector) public view returns (uint256) {
|
||
| 17 |
return calls[selector]; |
||
| 18 |
} |
||
| 19 | |||
| 20 |
function timesCalled(string calldata fnSig) public view returns (uint256) {
|
||
| 21 |
bytes32 selector = bytes32(uint256(keccak256(bytes(fnSig))) & (type(uint256).max << 224)); |
||
| 22 |
return calls[selector]; |
||
| 23 |
} |
||
| 24 | |||
| 25 |
function calledWithSelector(bytes32 selector, bytes calldata params) public view returns (bool) {
|
||
| 26 |
return callParams[selector][params[1:]] > 0; // Drop 0x byte string prefix |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function calledWith(string calldata fnSig, bytes calldata params) public view returns (bool) {
|
||
| 30 |
bytes32 selector = bytes32(uint256(keccak256(bytes(fnSig))) & (type(uint256).max << 224)); |
||
| 31 |
return callParams[selector][params[1:]] > 0; // Drop 0x byte string prefix |
||
| 32 |
} |
||
| 33 | |||
| 34 |
/// @notice exposes implementation contract address |
||
| 35 |
function _implementation() internal view override returns (address) {
|
||
| 36 |
return impl; |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function setImplementation(address _impl) external {
|
||
| 40 |
impl = _impl; |
||
| 41 |
} |
||
| 42 | |||
| 43 |
/// @notice Captures calls by selector |
||
| 44 |
function _beforeFallback() internal {
|
||
| 45 |
bytes32 selector = bytes32(msg.data[:5]); |
||
| 46 |
bytes memory params = msg.data[5:]; |
||
| 47 |
calls[selector]++; |
||
| 48 |
callParams[selector][params]++; |
||
| 49 |
} |
||
| 50 |
} |
||
| 51 |
| Lines covered: | 0 / 4 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {ERC6909Claims} from "../ERC6909Claims.sol";
|
||
| 6 |
import {Currency} from "../types/Currency.sol";
|
||
| 7 | |||
| 8 |
/// @notice Mock contract for testing ERC6909Claims |
||
| 9 |
contract MockERC6909Claims is ERC6909Claims {
|
||
| 10 |
/// @notice mocked mint logic |
||
| 11 |
function mint(address to, uint256 id, uint256 amount) public {
|
||
| 12 |
_mint(to, id, amount); |
||
| 13 |
} |
||
| 14 | |||
| 15 |
/// @notice mocked burn logic |
||
| 16 |
function burn(uint256 id, uint256 amount) public {
|
||
| 17 |
_burn(msg.sender, id, amount); |
||
| 18 |
} |
||
| 19 | |||
| 20 |
/// @notice mocked burn logic without checking sender allowance |
||
| 21 |
function burnFrom(address from, uint256 id, uint256 amount) public {
|
||
| 22 |
_burnFrom(from, id, amount); |
||
| 23 |
} |
||
| 24 |
} |
||
| 25 |
| Lines covered: | 0 / 55 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 6 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 9 |
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 10 |
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
|
||
| 11 | |||
| 12 |
contract MockHooks is IHooks {
|
||
| 13 |
using PoolIdLibrary for PoolKey; |
||
| 14 |
using Hooks for IHooks; |
||
| 15 | |||
| 16 |
bytes public beforeInitializeData; |
||
| 17 |
bytes public afterInitializeData; |
||
| 18 |
bytes public beforeAddLiquidityData; |
||
| 19 |
bytes public afterAddLiquidityData; |
||
| 20 |
bytes public beforeRemoveLiquidityData; |
||
| 21 |
bytes public afterRemoveLiquidityData; |
||
| 22 |
bytes public beforeSwapData; |
||
| 23 |
bytes public afterSwapData; |
||
| 24 |
bytes public beforeDonateData; |
||
| 25 |
bytes public afterDonateData; |
||
| 26 | |||
| 27 |
mapping(bytes4 => bytes4) public returnValues; |
||
| 28 | |||
| 29 |
mapping(PoolId => uint16) public lpFees; |
||
| 30 | |||
| 31 |
function beforeInitialize(address, PoolKey calldata, uint160, bytes calldata hookData) |
||
| 32 |
external |
||
| 33 |
override |
||
| 34 |
returns (bytes4) |
||
| 35 |
{
|
||
| 36 |
beforeInitializeData = hookData; |
||
| 37 |
bytes4 selector = MockHooks.beforeInitialize.selector; |
||
| 38 |
return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; |
||
| 39 |
} |
||
| 40 | |||
| 41 |
function afterInitialize(address, PoolKey calldata, uint160, int24, bytes calldata hookData) |
||
| 42 |
external |
||
| 43 |
override |
||
| 44 |
returns (bytes4) |
||
| 45 |
{
|
||
| 46 |
afterInitializeData = hookData; |
||
| 47 |
bytes4 selector = MockHooks.afterInitialize.selector; |
||
| 48 |
return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; |
||
| 49 |
} |
||
| 50 | |||
| 51 |
function beforeAddLiquidity( |
||
| 52 |
address, |
||
| 53 |
PoolKey calldata, |
||
| 54 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 55 |
bytes calldata hookData |
||
| 56 |
) external override returns (bytes4) {
|
||
| 57 |
beforeAddLiquidityData = hookData; |
||
| 58 |
bytes4 selector = MockHooks.beforeAddLiquidity.selector; |
||
| 59 |
return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function afterAddLiquidity( |
||
| 63 |
address, |
||
| 64 |
PoolKey calldata, |
||
| 65 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 66 |
BalanceDelta, |
||
| 67 |
bytes calldata hookData |
||
| 68 |
) external override returns (bytes4, BalanceDelta) {
|
||
| 69 |
afterAddLiquidityData = hookData; |
||
| 70 |
bytes4 selector = MockHooks.afterAddLiquidity.selector; |
||
| 71 |
return (returnValues[selector] == bytes4(0) ? selector : returnValues[selector], BalanceDeltaLibrary.ZERO_DELTA); |
||
| 72 |
} |
||
| 73 | |||
| 74 |
function beforeRemoveLiquidity( |
||
| 75 |
address, |
||
| 76 |
PoolKey calldata, |
||
| 77 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 78 |
bytes calldata hookData |
||
| 79 |
) external override returns (bytes4) {
|
||
| 80 |
beforeRemoveLiquidityData = hookData; |
||
| 81 |
bytes4 selector = MockHooks.beforeRemoveLiquidity.selector; |
||
| 82 |
return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function afterRemoveLiquidity( |
||
| 86 |
address, |
||
| 87 |
PoolKey calldata, |
||
| 88 |
IPoolManager.ModifyLiquidityParams calldata, |
||
| 89 |
BalanceDelta, |
||
| 90 |
bytes calldata hookData |
||
| 91 |
) external override returns (bytes4, BalanceDelta) {
|
||
| 92 |
afterRemoveLiquidityData = hookData; |
||
| 93 |
bytes4 selector = MockHooks.afterRemoveLiquidity.selector; |
||
| 94 |
return (returnValues[selector] == bytes4(0) ? selector : returnValues[selector], BalanceDeltaLibrary.ZERO_DELTA); |
||
| 95 |
} |
||
| 96 | |||
| 97 |
function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata hookData) |
||
| 98 |
external |
||
| 99 |
override |
||
| 100 |
returns (bytes4, BeforeSwapDelta, uint24) |
||
| 101 |
{
|
||
| 102 |
beforeSwapData = hookData; |
||
| 103 |
bytes4 selector = MockHooks.beforeSwap.selector; |
||
| 104 |
return ( |
||
| 105 |
returnValues[selector] == bytes4(0) ? selector : returnValues[selector], |
||
| 106 |
BeforeSwapDeltaLibrary.ZERO_DELTA, |
||
| 107 |
0 |
||
| 108 |
); |
||
| 109 |
} |
||
| 110 | |||
| 111 |
function afterSwap( |
||
| 112 |
address, |
||
| 113 |
PoolKey calldata, |
||
| 114 |
IPoolManager.SwapParams calldata, |
||
| 115 |
BalanceDelta, |
||
| 116 |
bytes calldata hookData |
||
| 117 |
) external override returns (bytes4, int128) {
|
||
| 118 |
afterSwapData = hookData; |
||
| 119 |
bytes4 selector = MockHooks.afterSwap.selector; |
||
| 120 |
return (returnValues[selector] == bytes4(0) ? selector : returnValues[selector], 0); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata hookData) |
||
| 124 |
external |
||
| 125 |
override |
||
| 126 |
returns (bytes4) |
||
| 127 |
{
|
||
| 128 |
beforeDonateData = hookData; |
||
| 129 |
bytes4 selector = MockHooks.beforeDonate.selector; |
||
| 130 |
return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; |
||
| 131 |
} |
||
| 132 | |||
| 133 |
function afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata hookData) |
||
| 134 |
external |
||
| 135 |
override |
||
| 136 |
returns (bytes4) |
||
| 137 |
{
|
||
| 138 |
afterDonateData = hookData; |
||
| 139 |
bytes4 selector = MockHooks.afterDonate.selector; |
||
| 140 |
return returnValues[selector] == bytes4(0) ? selector : returnValues[selector]; |
||
| 141 |
} |
||
| 142 | |||
| 143 |
function setReturnValue(bytes4 key, bytes4 value) external {
|
||
| 144 |
returnValues[key] = value; |
||
| 145 |
} |
||
| 146 | |||
| 147 |
function setlpFee(PoolKey calldata key, uint16 value) external {
|
||
| 148 |
lpFees[key.toId()] = value; |
||
| 149 |
} |
||
| 150 |
} |
||
| 151 |
| Lines covered: | 0 / 21 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: GPL-3.0-or-later |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 | |||
| 6 |
/// @dev This token contract simulates the ERC20 representation of a native token where on `transfer` and `transferFrom` the native balances are modified using a precompile |
||
| 7 |
contract NativeERC20 is Test {
|
||
| 8 |
string public name = "NativeERC20"; |
||
| 9 |
string public symbol = "NERC20"; |
||
| 10 |
uint8 public decimals = 18; |
||
| 11 | |||
| 12 |
event Approval(address indexed src, address indexed guy, uint256 wad); |
||
| 13 |
event Transfer(address indexed src, address indexed dst, uint256 wad); |
||
| 14 | |||
| 15 |
mapping(address => mapping(address => uint256)) public allowance; |
||
| 16 | |||
| 17 |
function totalSupply() public view returns (uint256) {
|
||
| 18 |
return address(this).balance; |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function approve(address guy, uint256 wad) public returns (bool) {
|
||
| 22 |
allowance[msg.sender][guy] = wad; |
||
| 23 |
emit Approval(msg.sender, guy, wad); |
||
| 24 |
return true; |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function transfer(address dst, uint256 wad) public returns (bool) {
|
||
| 28 |
return transferFrom(msg.sender, dst, wad); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
|
||
| 32 |
require(src.balance >= wad); |
||
| 33 | |||
| 34 |
if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {
|
||
| 35 |
require(allowance[src][msg.sender] >= wad, ""); |
||
| 36 |
allowance[src][msg.sender] -= wad; |
||
| 37 |
} |
||
| 38 | |||
| 39 |
vm.deal(src, src.balance - wad); |
||
| 40 |
vm.deal(dst, dst.balance + wad); |
||
| 41 | |||
| 42 |
emit Transfer(src, dst, wad); |
||
| 43 | |||
| 44 |
return true; |
||
| 45 |
} |
||
| 46 | |||
| 47 |
function balanceOf(address account) external view returns (uint256) {
|
||
| 48 |
return account.balance; |
||
| 49 |
} |
||
| 50 |
} |
||
| 51 |
| Lines covered: | 0 / 14 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {NoDelegateCall} from "../NoDelegateCall.sol";
|
||
| 5 | |||
| 6 |
contract NoDelegateCallTest is NoDelegateCall {
|
||
| 7 |
function canBeDelegateCalled() public view returns (uint256) {
|
||
| 8 |
return block.timestamp / 5; |
||
| 9 |
} |
||
| 10 | |||
| 11 |
function cannotBeDelegateCalled() public view noDelegateCall returns (uint256) {
|
||
| 12 |
return block.timestamp / 5; |
||
| 13 |
} |
||
| 14 | |||
| 15 |
function getGasCostOfCanBeDelegateCalled() external view returns (uint256) {
|
||
| 16 |
uint256 gasBefore = gasleft(); |
||
| 17 |
canBeDelegateCalled(); |
||
| 18 |
return gasBefore - gasleft(); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function getGasCostOfCannotBeDelegateCalled() external view returns (uint256) {
|
||
| 22 |
uint256 gasBefore = gasleft(); |
||
| 23 |
cannotBeDelegateCalled(); |
||
| 24 |
return gasBefore - gasleft(); |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function callsIntoNoDelegateCallFunction() external view {
|
||
| 28 |
noDelegateCallPrivate(); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function noDelegateCallPrivate() private view noDelegateCall {}
|
||
| 32 |
} |
||
| 33 |
| Lines covered: | 1 / 12 (8.3%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 6 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 9 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 10 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 11 | |||
| 12 |
contract PoolClaimsTest is PoolTestBase {
|
||
| 13 |
using CurrencySettler for Currency; |
||
| 14 |
using SafeCast for uint256; |
||
| 15 | |||
| 16 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 17 | |||
| 18 |
struct CallbackData {
|
||
| 19 |
address sender; |
||
| 20 |
address user; |
||
| 21 |
Currency currency; |
||
| 22 |
uint256 amount; |
||
| 23 |
bool deposit; |
||
| 24 |
} |
||
| 25 | |||
| 26 |
/// @notice Convert ERC20 into a claimable 6909 |
||
| 27 |
function deposit(Currency currency, address user, uint256 amount) external payable {
|
||
| 28 |
manager.unlock(abi.encode(CallbackData(msg.sender, user, currency, amount, true))); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
/// @notice Redeem claimable 6909 for ERC20 |
||
| 32 |
function withdraw(Currency currency, address user, uint256 amount) external payable {
|
||
| 33 |
manager.unlock(abi.encode(CallbackData(msg.sender, user, currency, amount, false))); |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 37 |
require(msg.sender == address(manager)); |
||
| 38 | |||
| 39 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 40 | |||
| 41 |
if (data.deposit) {
|
||
| 42 |
data.currency.take(manager, data.user, data.amount, true); // mint 6909 |
||
| 43 |
data.currency.settle(manager, data.user, data.amount, false); // transfer ERC20 |
||
| 44 |
} else {
|
||
| 45 |
data.currency.settle(manager, data.user, data.amount, true); // burn 6909 |
||
| 46 |
data.currency.take(manager, data.user, data.amount, false); // claim ERC20 |
||
| 47 |
} |
||
| 48 | |||
| 49 |
return abi.encode(0); |
||
| 50 |
} |
||
| 51 |
} |
||
| 52 |
| Lines covered: | 1 / 23 (4.3%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency, CurrencyLibrary} from "../types/Currency.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 7 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 8 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 9 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 10 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 11 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 12 | |||
| 13 |
contract PoolDonateTest is PoolTestBase {
|
||
| 14 |
using CurrencySettler for Currency; |
||
| 15 |
using Hooks for IHooks; |
||
| 16 | |||
| 17 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 18 | |||
| 19 |
struct CallbackData {
|
||
| 20 |
address sender; |
||
| 21 |
PoolKey key; |
||
| 22 |
uint256 amount0; |
||
| 23 |
uint256 amount1; |
||
| 24 |
bytes hookData; |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes memory hookData) |
||
| 28 |
external |
||
| 29 |
payable |
||
| 30 |
returns (BalanceDelta delta) |
||
| 31 |
{
|
||
| 32 |
delta = abi.decode( |
||
| 33 |
manager.unlock(abi.encode(CallbackData(msg.sender, key, amount0, amount1, hookData))), (BalanceDelta) |
||
| 34 |
); |
||
| 35 | |||
| 36 |
uint256 ethBalance = address(this).balance; |
||
| 37 |
if (ethBalance > 0) {
|
||
| 38 |
CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); |
||
| 39 |
} |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 43 |
require(msg.sender == address(manager)); |
||
| 44 | |||
| 45 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 46 | |||
| 47 |
(,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 48 |
(,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 49 | |||
| 50 |
require(deltaBefore0 == 0, "deltaBefore0 is not 0"); |
||
| 51 |
require(deltaBefore1 == 0, "deltaBefore1 is not 0"); |
||
| 52 | |||
| 53 |
BalanceDelta delta = manager.donate(data.key, data.amount0, data.amount1, data.hookData); |
||
| 54 | |||
| 55 |
(,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 56 |
(,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 57 | |||
| 58 |
require(deltaAfter0 == -int256(data.amount0), "deltaAfter0 is not equal to -int256(data.amount0)"); |
||
| 59 |
require(deltaAfter1 == -int256(data.amount1), "deltaAfter1 is not equal to -int256(data.amount1)"); |
||
| 60 | |||
| 61 |
if (deltaAfter0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-deltaAfter0), false); |
||
| 62 |
if (deltaAfter1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-deltaAfter1), false); |
||
| 63 |
if (deltaAfter0 > 0) data.key.currency0.take(manager, data.sender, uint256(deltaAfter0), false); |
||
| 64 |
if (deltaAfter1 > 0) data.key.currency1.take(manager, data.sender, uint256(deltaAfter1), false); |
||
| 65 | |||
| 66 |
return abi.encode(delta); |
||
| 67 |
} |
||
| 68 |
} |
||
| 69 |
| Lines covered: | 0 / 5 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 5 |
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
|
||
| 6 | |||
| 7 |
contract PoolEmptyUnlockTest is IUnlockCallback {
|
||
| 8 |
event UnlockCallback(); |
||
| 9 | |||
| 10 |
IPoolManager manager; |
||
| 11 | |||
| 12 |
constructor(IPoolManager _manager) {
|
||
| 13 |
manager = _manager; |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function unlock() external {
|
||
| 17 |
manager.unlock("");
|
||
| 18 |
} |
||
| 19 | |||
| 20 |
/// @notice Called by the pool manager on `msg.sender` when the manager is unlocked |
||
| 21 |
function unlockCallback(bytes calldata) external override returns (bytes memory) {
|
||
| 22 |
emit UnlockCallback(); |
||
| 23 |
return ""; |
||
| 24 |
} |
||
| 25 |
} |
||
| 26 |
| Lines covered: | 1 / 30 (3.3%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 9 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 10 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 11 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 12 |
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
|
||
| 13 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 14 |
import {StateLibrary} from "../libraries/StateLibrary.sol";
|
||
| 15 | |||
| 16 |
contract PoolModifyLiquidityTest is PoolTestBase {
|
||
| 17 |
using CurrencySettler for Currency; |
||
| 18 |
using Hooks for IHooks; |
||
| 19 |
using LPFeeLibrary for uint24; |
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using StateLibrary for IPoolManager; |
||
| 22 | |||
| 23 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 24 | |||
| 25 |
struct CallbackData {
|
||
| 26 |
address sender; |
||
| 27 |
PoolKey key; |
||
| 28 |
IPoolManager.ModifyLiquidityParams params; |
||
| 29 |
bytes hookData; |
||
| 30 |
bool settleUsingBurn; |
||
| 31 |
bool takeClaims; |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function modifyLiquidity( |
||
| 35 |
PoolKey memory key, |
||
| 36 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 37 |
bytes memory hookData |
||
| 38 |
) external payable returns (BalanceDelta delta) {
|
||
| 39 |
delta = modifyLiquidity(key, params, hookData, false, false); |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function modifyLiquidity( |
||
| 43 |
PoolKey memory key, |
||
| 44 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 45 |
bytes memory hookData, |
||
| 46 |
bool settleUsingBurn, |
||
| 47 |
bool takeClaims |
||
| 48 |
) public payable returns (BalanceDelta delta) {
|
||
| 49 |
delta = abi.decode( |
||
| 50 |
manager.unlock(abi.encode(CallbackData(msg.sender, key, params, hookData, settleUsingBurn, takeClaims))), |
||
| 51 |
(BalanceDelta) |
||
| 52 |
); |
||
| 53 | |||
| 54 |
uint256 ethBalance = address(this).balance; |
||
| 55 |
if (ethBalance > 0) {
|
||
| 56 |
CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); |
||
| 57 |
} |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 61 |
require(msg.sender == address(manager)); |
||
| 62 | |||
| 63 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 64 | |||
| 65 |
uint128 liquidityBefore = manager.getPosition( |
||
| 66 |
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt |
||
| 67 |
).liquidity; |
||
| 68 | |||
| 69 |
(BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData); |
||
| 70 | |||
| 71 |
uint128 liquidityAfter = manager.getPosition( |
||
| 72 |
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt |
||
| 73 |
).liquidity; |
||
| 74 | |||
| 75 |
(,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 76 |
(,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 77 | |||
| 78 |
require( |
||
| 79 |
int128(liquidityBefore) + data.params.liquidityDelta == int128(liquidityAfter), "liquidity change incorrect" |
||
| 80 |
); |
||
| 81 | |||
| 82 |
if (data.params.liquidityDelta < 0) {
|
||
| 83 |
assert(delta0 > 0 || delta1 > 0); |
||
| 84 |
assert(!(delta0 < 0 || delta1 < 0)); |
||
| 85 |
} else if (data.params.liquidityDelta > 0) {
|
||
| 86 |
assert(delta0 < 0 || delta1 < 0); |
||
| 87 |
assert(!(delta0 > 0 || delta1 > 0)); |
||
| 88 |
} |
||
| 89 | |||
| 90 |
if (delta0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-delta0), data.settleUsingBurn); |
||
| 91 |
if (delta1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-delta1), data.settleUsingBurn); |
||
| 92 |
if (delta0 > 0) data.key.currency0.take(manager, data.sender, uint256(delta0), data.takeClaims); |
||
| 93 |
if (delta1 > 0) data.key.currency1.take(manager, data.sender, uint256(delta1), data.takeClaims); |
||
| 94 | |||
| 95 |
return abi.encode(delta); |
||
| 96 |
} |
||
| 97 |
} |
||
| 98 |
| Lines covered: | 1 / 19 (5.3%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 9 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 10 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 11 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 12 |
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
|
||
| 13 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 14 |
import {Constants} from "../../test/utils/Constants.sol";
|
||
| 15 | |||
| 16 |
contract PoolModifyLiquidityTestNoChecks is PoolTestBase {
|
||
| 17 |
using CurrencySettler for Currency; |
||
| 18 |
using Hooks for IHooks; |
||
| 19 |
using LPFeeLibrary for uint24; |
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 | |||
| 22 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 23 | |||
| 24 |
struct CallbackData {
|
||
| 25 |
address sender; |
||
| 26 |
PoolKey key; |
||
| 27 |
IPoolManager.ModifyLiquidityParams params; |
||
| 28 |
bytes hookData; |
||
| 29 |
bool settleUsingBurn; |
||
| 30 |
bool takeClaims; |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function modifyLiquidity( |
||
| 34 |
PoolKey memory key, |
||
| 35 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 36 |
bytes memory hookData |
||
| 37 |
) external payable returns (BalanceDelta delta) {
|
||
| 38 |
delta = modifyLiquidity(key, params, hookData, false, false); |
||
| 39 |
} |
||
| 40 | |||
| 41 |
function modifyLiquidity( |
||
| 42 |
PoolKey memory key, |
||
| 43 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 44 |
bytes memory hookData, |
||
| 45 |
bool settleUsingBurn, |
||
| 46 |
bool takeClaims |
||
| 47 |
) public payable returns (BalanceDelta delta) {
|
||
| 48 |
delta = abi.decode( |
||
| 49 |
manager.unlock(abi.encode(CallbackData(msg.sender, key, params, hookData, settleUsingBurn, takeClaims))), |
||
| 50 |
(BalanceDelta) |
||
| 51 |
); |
||
| 52 | |||
| 53 |
uint256 ethBalance = address(this).balance; |
||
| 54 |
if (ethBalance > 0) {
|
||
| 55 |
CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); |
||
| 56 |
} |
||
| 57 |
} |
||
| 58 | |||
| 59 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 60 |
require(msg.sender == address(manager)); |
||
| 61 | |||
| 62 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 63 | |||
| 64 |
(BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData); |
||
| 65 | |||
| 66 |
int256 delta0 = delta.amount0(); |
||
| 67 |
int256 delta1 = delta.amount1(); |
||
| 68 | |||
| 69 |
if (delta0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-delta0), data.settleUsingBurn); |
||
| 70 |
if (delta1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-delta1), data.settleUsingBurn); |
||
| 71 |
if (delta0 > 0) data.key.currency0.take(manager, data.sender, uint256(delta0), data.takeClaims); |
||
| 72 |
if (delta1 > 0) data.key.currency1.take(manager, data.sender, uint256(delta1), data.takeClaims); |
||
| 73 | |||
| 74 |
return abi.encode(delta); |
||
| 75 |
} |
||
| 76 |
} |
||
| 77 |
| Lines covered: | 10 / 118 (8.5%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 5 |
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
|
||
| 6 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {Constants} from "../../test/utils/Constants.sol";
|
||
| 9 |
import {Test} from "forge-std/Test.sol";
|
||
| 10 |
import {BalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 11 |
import {Currency} from "../types/Currency.sol";
|
||
| 12 |
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 13 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 14 |
import {StateLibrary} from "../libraries/StateLibrary.sol";
|
||
| 15 |
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
|
||
| 16 | |||
| 17 |
enum Action {
|
||
| 18 |
NESTED_SELF_UNLOCK, |
||
| 19 |
NESTED_EXECUTOR_UNLOCK, |
||
| 20 |
SWAP_AND_SETTLE, |
||
| 21 |
DONATE_AND_SETTLE, |
||
| 22 |
ADD_LIQUIDITY_AND_SETTLE, |
||
| 23 |
REMOVE_LIQUIDITY_AND_SETTLE, |
||
| 24 |
INITIALIZE |
||
| 25 |
} |
||
| 26 | |||
| 27 |
contract PoolNestedActionsTest is Test, IUnlockCallback {
|
||
| 28 |
using StateLibrary for IPoolManager; |
||
| 29 |
using TransientStateLibrary for IPoolManager; |
||
| 30 | |||
| 31 |
IPoolManager manager; |
||
| 32 |
√ 13
|
NestedActionExecutor public executor; |
|
| 33 |
address user; |
||
| 34 | |||
| 35 |
constructor(IPoolManager _manager) {
|
||
| 36 |
√ 1
|
manager = _manager; |
|
| 37 |
√ 3
|
user = msg.sender; |
|
| 38 |
√ 7
|
executor = new NestedActionExecutor(manager, user); |
|
| 39 |
} |
||
| 40 | |||
| 41 |
function unlock(bytes calldata data) external {
|
||
| 42 |
manager.unlock(data); |
||
| 43 |
} |
||
| 44 | |||
| 45 |
/// @notice Called by the pool manager on `msg.sender` when the manager is unlocked |
||
| 46 |
function unlockCallback(bytes calldata data) external override returns (bytes memory) {
|
||
| 47 |
Action[] memory actions = abi.decode(data, (Action[])); |
||
| 48 |
if (actions.length == 1 && actions[0] == Action.NESTED_SELF_UNLOCK) {
|
||
| 49 |
_nestedUnlock(); |
||
| 50 |
} else {
|
||
| 51 |
executor.execute(actions); |
||
| 52 |
} |
||
| 53 |
return ""; |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function _nestedUnlock() internal {
|
||
| 57 |
bool unlocked = manager.isUnlocked(); |
||
| 58 |
assertEq(unlocked, true); |
||
| 59 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyUnlocked.selector)); |
||
| 60 |
manager.unlock("");
|
||
| 61 |
unlocked = manager.isUnlocked(); |
||
| 62 |
assertEq(unlocked, true); |
||
| 63 |
} |
||
| 64 |
} |
||
| 65 | |||
| 66 |
contract NestedActionExecutor is Test, PoolTestBase {
|
||
| 67 |
using StateLibrary for IPoolManager; |
||
| 68 |
using TransientStateLibrary for IPoolManager; |
||
| 69 |
using CurrencySettler for Currency; |
||
| 70 |
using PoolIdLibrary for PoolKey; |
||
| 71 | |||
| 72 |
PoolKey internal key; |
||
| 73 |
address user; |
||
| 74 | |||
| 75 |
error KeyNotSet(); |
||
| 76 | |||
| 77 |
IPoolManager.ModifyLiquidityParams internal ADD_LIQUIDITY_PARAMS = |
||
| 78 |
√ 2
|
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
|
|
| 79 | |||
| 80 |
IPoolManager.ModifyLiquidityParams internal REMOVE_LIQUIDITY_PARAMS = |
||
| 81 |
√ 18
|
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18, salt: 0});
|
|
| 82 | |||
| 83 |
IPoolManager.SwapParams internal SWAP_PARAMS = |
||
| 84 |
√ 13
|
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: Constants.SQRT_PRICE_1_2});
|
|
| 85 | |||
| 86 |
√ 1
|
uint256 internal DONATE_AMOUNT0 = 12345e6; |
|
| 87 |
√ 1
|
uint256 internal DONATE_AMOUNT1 = 98765e4; |
|
| 88 | |||
| 89 |
constructor(IPoolManager _manager, address _user) PoolTestBase(_manager) {
|
||
| 90 |
√ 1
|
user = _user; |
|
| 91 |
} |
||
| 92 | |||
| 93 |
function setKey(PoolKey memory _key) external {
|
||
| 94 |
key = _key; |
||
| 95 |
} |
||
| 96 | |||
| 97 |
function execute(Action[] memory actions) public {
|
||
| 98 |
if (Currency.unwrap(key.currency0) == address(0)) revert KeyNotSet(); |
||
| 99 |
for (uint256 i = 0; i < actions.length; i++) {
|
||
| 100 |
Action action = actions[i]; |
||
| 101 |
if (action == Action.NESTED_EXECUTOR_UNLOCK) _nestedUnlock(); |
||
| 102 |
else if (action == Action.SWAP_AND_SETTLE) _swap(msg.sender); |
||
| 103 |
else if (action == Action.ADD_LIQUIDITY_AND_SETTLE) _addLiquidity(msg.sender); |
||
| 104 |
else if (action == Action.REMOVE_LIQUIDITY_AND_SETTLE) _removeLiquidity(msg.sender); |
||
| 105 |
else if (action == Action.DONATE_AND_SETTLE) _donate(msg.sender); |
||
| 106 |
else if (action == Action.INITIALIZE) _initialize(); |
||
| 107 |
} |
||
| 108 |
} |
||
| 109 | |||
| 110 |
function _nestedUnlock() internal {
|
||
| 111 |
bool unlocked = manager.isUnlocked(); |
||
| 112 |
assertEq(unlocked, true); |
||
| 113 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyUnlocked.selector)); |
||
| 114 |
manager.unlock("");
|
||
| 115 |
unlocked = manager.isUnlocked(); |
||
| 116 |
assertEq(unlocked, true); |
||
| 117 |
} |
||
| 118 | |||
| 119 |
function _swap(address caller) internal {
|
||
| 120 |
bool unlocked = manager.isUnlocked(); |
||
| 121 |
assertEq(unlocked, true); |
||
| 122 |
(,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller); |
||
| 123 |
(,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller); |
||
| 124 |
(,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 125 |
(,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 126 | |||
| 127 |
BalanceDelta delta = manager.swap(key, SWAP_PARAMS, ""); |
||
| 128 | |||
| 129 |
(,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller); |
||
| 130 |
(,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller); |
||
| 131 |
(,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 132 |
(,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 133 | |||
| 134 |
assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0"); |
||
| 135 |
assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1"); |
||
| 136 |
assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0"); |
||
| 137 |
assertEq(deltaThisBefore1 + 98, deltaThisAfter1, "Executor delta 1"); |
||
| 138 |
assertEq(delta.amount0(), deltaThisAfter0, "Swap delta 0"); |
||
| 139 |
assertEq(delta.amount1(), deltaThisAfter1, "Swap delta 1"); |
||
| 140 | |||
| 141 |
key.currency0.settle(manager, user, uint256(-deltaThisAfter0), false); |
||
| 142 |
key.currency1.take(manager, user, uint256(deltaThisAfter1), false); |
||
| 143 |
} |
||
| 144 | |||
| 145 |
function _addLiquidity(address caller) internal {
|
||
| 146 |
bool unlocked = manager.isUnlocked(); |
||
| 147 |
assertEq(unlocked, true); |
||
| 148 |
(,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller); |
||
| 149 |
(,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller); |
||
| 150 |
(,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 151 |
(,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 152 | |||
| 153 |
(BalanceDelta delta,) = manager.modifyLiquidity(key, ADD_LIQUIDITY_PARAMS, ""); |
||
| 154 | |||
| 155 |
(,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller); |
||
| 156 |
(,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller); |
||
| 157 |
(,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 158 |
(,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 159 | |||
| 160 |
assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0"); |
||
| 161 |
assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1"); |
||
| 162 |
assertEq(deltaThisBefore0 + delta.amount0(), deltaThisAfter0, "Executor delta 0"); |
||
| 163 |
assertEq(deltaThisBefore1 + delta.amount1(), deltaThisAfter1, "Executor delta 1"); |
||
| 164 | |||
| 165 |
key.currency0.settle(manager, user, uint256(-deltaThisAfter0), false); |
||
| 166 |
key.currency1.settle(manager, user, uint256(-deltaThisAfter1), false); |
||
| 167 |
} |
||
| 168 | |||
| 169 |
// cannot remove non-existent liquidity - need to perform an add before this removal |
||
| 170 |
function _removeLiquidity(address caller) internal {
|
||
| 171 |
bool unlocked = manager.isUnlocked(); |
||
| 172 |
assertEq(unlocked, true); |
||
| 173 |
(,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller); |
||
| 174 |
(,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller); |
||
| 175 |
(,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 176 |
(,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 177 | |||
| 178 |
(BalanceDelta delta,) = manager.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ""); |
||
| 179 | |||
| 180 |
(,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller); |
||
| 181 |
(,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller); |
||
| 182 |
(,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 183 |
(,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 184 | |||
| 185 |
assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0"); |
||
| 186 |
assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1"); |
||
| 187 |
assertEq(deltaThisBefore0 + delta.amount0(), deltaThisAfter0, "Executor delta 0"); |
||
| 188 |
assertEq(deltaThisBefore1 + delta.amount1(), deltaThisAfter1, "Executor delta 1"); |
||
| 189 | |||
| 190 |
key.currency0.take(manager, user, uint256(deltaThisAfter0), false); |
||
| 191 |
key.currency1.take(manager, user, uint256(deltaThisAfter1), false); |
||
| 192 |
} |
||
| 193 | |||
| 194 |
function _donate(address caller) internal {
|
||
| 195 |
bool unlocked = manager.isUnlocked(); |
||
| 196 |
assertEq(unlocked, true); |
||
| 197 |
(,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller); |
||
| 198 |
(,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller); |
||
| 199 |
(,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 200 |
(,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 201 | |||
| 202 |
BalanceDelta delta = manager.donate(key, DONATE_AMOUNT0, DONATE_AMOUNT1, ""); |
||
| 203 | |||
| 204 |
(,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller); |
||
| 205 |
(,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller); |
||
| 206 |
(,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this)); |
||
| 207 |
(,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this)); |
||
| 208 | |||
| 209 |
assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0"); |
||
| 210 |
assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1"); |
||
| 211 |
assertEq(deltaThisBefore0 - int256(DONATE_AMOUNT0), deltaThisAfter0, "Executor delta 0"); |
||
| 212 |
assertEq(deltaThisBefore1 - int256(DONATE_AMOUNT1), deltaThisAfter1, "Executor delta 1"); |
||
| 213 |
assertEq(-delta.amount0(), int256(DONATE_AMOUNT0), "Donate delta 0"); |
||
| 214 |
assertEq(-delta.amount1(), int256(DONATE_AMOUNT1), "Donate delta 1"); |
||
| 215 | |||
| 216 |
key.currency0.settle(manager, user, uint256(-deltaThisAfter0), false); |
||
| 217 |
key.currency1.settle(manager, user, uint256(-deltaThisAfter1), false); |
||
| 218 |
} |
||
| 219 | |||
| 220 |
function _initialize() internal {
|
||
| 221 |
bool unlocked = manager.isUnlocked(); |
||
| 222 |
assertEq(unlocked, true); |
||
| 223 |
key.tickSpacing = 50; |
||
| 224 |
PoolId id = key.toId(); |
||
| 225 |
(uint256 price,,,) = manager.getSlot0(id); |
||
| 226 |
assertEq(price, 0); |
||
| 227 |
manager.initialize(key, Constants.SQRT_PRICE_1_2, Constants.ZERO_BYTES); |
||
| 228 |
(price,,,) = manager.getSlot0(id); |
||
| 229 |
assertEq(price, Constants.SQRT_PRICE_1_2); |
||
| 230 |
} |
||
| 231 | |||
| 232 |
// This will never actually be used - its just to allow us to use the PoolTestBase helper contact |
||
| 233 |
function unlockCallback(bytes calldata) external pure override returns (bytes memory) {
|
||
| 234 |
return ""; |
||
| 235 |
} |
||
| 236 |
} |
||
| 237 |
| Lines covered: | 1 / 6 (16.7%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 5 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 6 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 7 | |||
| 8 |
contract PoolSettleTest is PoolTestBase {
|
||
| 9 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 10 | |||
| 11 |
function settle() external payable {
|
||
| 12 |
manager.unlock("");
|
||
| 13 |
} |
||
| 14 | |||
| 15 |
function unlockCallback(bytes calldata) external returns (bytes memory) {
|
||
| 16 |
require(msg.sender == address(manager)); |
||
| 17 | |||
| 18 |
manager.settle{value: address(this).balance}();
|
||
| 19 | |||
| 20 |
return abi.encode(0); |
||
| 21 |
} |
||
| 22 |
} |
||
| 23 |
| Lines covered: | 1 / 39 (2.6%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 9 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 10 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 11 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 12 | |||
| 13 |
contract PoolSwapTest is PoolTestBase {
|
||
| 14 |
using CurrencySettler for Currency; |
||
| 15 |
using Hooks for IHooks; |
||
| 16 | |||
| 17 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 18 | |||
| 19 |
error NoSwapOccurred(); |
||
| 20 | |||
| 21 |
struct CallbackData {
|
||
| 22 |
address sender; |
||
| 23 |
TestSettings testSettings; |
||
| 24 |
PoolKey key; |
||
| 25 |
IPoolManager.SwapParams params; |
||
| 26 |
bytes hookData; |
||
| 27 |
} |
||
| 28 | |||
| 29 |
struct TestSettings {
|
||
| 30 |
bool takeClaims; |
||
| 31 |
bool settleUsingBurn; |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function swap( |
||
| 35 |
PoolKey memory key, |
||
| 36 |
IPoolManager.SwapParams memory params, |
||
| 37 |
TestSettings memory testSettings, |
||
| 38 |
bytes memory hookData |
||
| 39 |
) external payable returns (BalanceDelta delta) {
|
||
| 40 |
delta = abi.decode( |
||
| 41 |
manager.unlock(abi.encode(CallbackData(msg.sender, testSettings, key, params, hookData))), (BalanceDelta) |
||
| 42 |
); |
||
| 43 | |||
| 44 |
uint256 ethBalance = address(this).balance; |
||
| 45 |
if (ethBalance > 0) CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 49 |
require(msg.sender == address(manager)); |
||
| 50 | |||
| 51 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 52 | |||
| 53 |
(,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 54 |
(,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 55 | |||
| 56 |
require(deltaBefore0 == 0, "deltaBefore0 is not equal to 0"); |
||
| 57 |
require(deltaBefore1 == 0, "deltaBefore1 is not equal to 0"); |
||
| 58 | |||
| 59 |
BalanceDelta delta = manager.swap(data.key, data.params, data.hookData); |
||
| 60 | |||
| 61 |
(,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 62 |
(,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 63 | |||
| 64 |
if (data.params.zeroForOne) {
|
||
| 65 |
if (data.params.amountSpecified < 0) {
|
||
| 66 |
// exact input, 0 for 1 |
||
| 67 |
require( |
||
| 68 |
deltaAfter0 >= data.params.amountSpecified, |
||
| 69 |
"deltaAfter0 is not greater than or equal to data.params.amountSpecified" |
||
| 70 |
); |
||
| 71 |
require(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0"); |
||
| 72 |
require(deltaAfter1 >= 0, "deltaAfter1 is not greater than or equal to 0"); |
||
| 73 |
} else {
|
||
| 74 |
// exact output, 0 for 1 |
||
| 75 |
require(deltaAfter0 <= 0, "deltaAfter0 is not less than or equal to zero"); |
||
| 76 |
require(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1"); |
||
| 77 |
require( |
||
| 78 |
deltaAfter1 <= data.params.amountSpecified, |
||
| 79 |
"deltaAfter1 is not less than or equal to data.params.amountSpecified" |
||
| 80 |
); |
||
| 81 |
} |
||
| 82 |
} else {
|
||
| 83 |
if (data.params.amountSpecified < 0) {
|
||
| 84 |
// exact input, 1 for 0 |
||
| 85 |
require( |
||
| 86 |
deltaAfter1 >= data.params.amountSpecified, |
||
| 87 |
"deltaAfter1 is not greater than or equal to data.params.amountSpecified" |
||
| 88 |
); |
||
| 89 |
require(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1"); |
||
| 90 |
require(deltaAfter0 >= 0, "deltaAfter0 is not greater than or equal to 0"); |
||
| 91 |
} else {
|
||
| 92 |
// exact output, 1 for 0 |
||
| 93 |
require(deltaAfter1 <= 0, "deltaAfter1 is not less than or equal to 0"); |
||
| 94 |
require(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0"); |
||
| 95 |
require( |
||
| 96 |
deltaAfter0 <= data.params.amountSpecified, |
||
| 97 |
"deltaAfter0 is not less than or equal to data.params.amountSpecified" |
||
| 98 |
); |
||
| 99 |
} |
||
| 100 |
} |
||
| 101 | |||
| 102 |
if (deltaAfter0 < 0) {
|
||
| 103 |
data.key.currency0.settle(manager, data.sender, uint256(-deltaAfter0), data.testSettings.settleUsingBurn); |
||
| 104 |
} |
||
| 105 |
if (deltaAfter1 < 0) {
|
||
| 106 |
data.key.currency1.settle(manager, data.sender, uint256(-deltaAfter1), data.testSettings.settleUsingBurn); |
||
| 107 |
} |
||
| 108 |
if (deltaAfter0 > 0) {
|
||
| 109 |
data.key.currency0.take(manager, data.sender, uint256(deltaAfter0), data.testSettings.takeClaims); |
||
| 110 |
} |
||
| 111 |
if (deltaAfter1 > 0) {
|
||
| 112 |
data.key.currency1.take(manager, data.sender, uint256(deltaAfter1), data.testSettings.takeClaims); |
||
| 113 |
} |
||
| 114 | |||
| 115 |
return abi.encode(delta); |
||
| 116 |
} |
||
| 117 |
} |
||
| 118 |
| Lines covered: | 1 / 17 (5.9%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 7 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 8 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 9 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 10 | |||
| 11 |
contract PoolTakeTest is PoolTestBase {
|
||
| 12 |
using CurrencySettler for Currency; |
||
| 13 |
using SafeCast for uint256; |
||
| 14 | |||
| 15 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 16 | |||
| 17 |
struct CallbackData {
|
||
| 18 |
address sender; |
||
| 19 |
PoolKey key; |
||
| 20 |
uint256 amount0; |
||
| 21 |
uint256 amount1; |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function take(PoolKey memory key, uint256 amount0, uint256 amount1) external payable {
|
||
| 25 |
manager.unlock(abi.encode(CallbackData(msg.sender, key, amount0, amount1))); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 29 |
require(msg.sender == address(manager)); |
||
| 30 | |||
| 31 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 32 | |||
| 33 |
if (data.amount0 > 0) _testTake(data.key.currency0, data.sender, data.amount0); |
||
| 34 |
if (data.amount1 > 0) _testTake(data.key.currency1, data.sender, data.amount1); |
||
| 35 | |||
| 36 |
return abi.encode(0); |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function _testTake(Currency currency, address sender, uint256 amount) internal {
|
||
| 40 |
(uint256 userBalBefore, uint256 pmBalBefore, int256 deltaBefore) = |
||
| 41 |
_fetchBalances(currency, sender, address(this)); |
||
| 42 |
require(deltaBefore == 0, "deltaBefore is not equal to 0"); |
||
| 43 | |||
| 44 |
currency.take(manager, sender, amount, false); |
||
| 45 | |||
| 46 |
(uint256 userBalAfter, uint256 pmBalAfter, int256 deltaAfter) = _fetchBalances(currency, sender, address(this)); |
||
| 47 | |||
| 48 |
require(deltaAfter == -amount.toInt128(), "deltaAfter is not equal to -amount.toInt128()"); |
||
| 49 | |||
| 50 |
require( |
||
| 51 |
userBalAfter - userBalBefore == amount, |
||
| 52 |
"the difference between userBalAfter and userBalBefore is not equal to amount" |
||
| 53 |
); |
||
| 54 |
require( |
||
| 55 |
pmBalBefore - pmBalAfter == amount, |
||
| 56 |
"the difference between pmBalBefore and pmBalAfter is not equal to amount" |
||
| 57 |
); |
||
| 58 | |||
| 59 |
currency.settle(manager, sender, amount, false); |
||
| 60 |
} |
||
| 61 |
} |
||
| 62 |
| Lines covered: | 1 / 6 (16.7%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 6 | |||
| 7 |
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
|
||
| 8 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 9 | |||
| 10 |
import {StateLibrary} from "../libraries/StateLibrary.sol";
|
||
| 11 |
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
|
||
| 12 | |||
| 13 |
abstract contract PoolTestBase is IUnlockCallback {
|
||
| 14 |
using StateLibrary for IPoolManager; |
||
| 15 |
using TransientStateLibrary for IPoolManager; |
||
| 16 | |||
| 17 |
IPoolManager public immutable manager; |
||
| 18 | |||
| 19 |
constructor(IPoolManager _manager) {
|
||
| 20 |
√ 29
|
manager = _manager; |
|
| 21 |
} |
||
| 22 | |||
| 23 |
function _fetchBalances(Currency currency, address user, address deltaHolder) |
||
| 24 |
internal |
||
| 25 |
view |
||
| 26 |
returns (uint256 userBalance, uint256 poolBalance, int256 delta) |
||
| 27 |
{
|
||
| 28 |
userBalance = currency.balanceOf(user); |
||
| 29 |
poolBalance = currency.balanceOf(address(manager)); |
||
| 30 |
delta = manager.currencyDelta(deltaHolder, currency); |
||
| 31 |
} |
||
| 32 |
} |
||
| 33 |
| Lines covered: | 7 / 21 (33.3%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {IProtocolFeeController} from "../interfaces/IProtocolFeeController.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 | |||
| 9 |
√ 17
|
contract ProtocolFeeControllerTest is IProtocolFeeController {
|
|
| 10 |
using PoolIdLibrary for PoolKey; |
||
| 11 | |||
| 12 |
mapping(PoolId => uint24) public protocolFee; |
||
| 13 | |||
| 14 |
√ 1
|
⟳ 1
|
function protocolFeeForPool(PoolKey memory key) external view returns (uint24) {
|
| 15 |
√ 2
|
⟳ 2
|
return protocolFee[key.toId()]; |
| 16 |
} |
||
| 17 | |||
| 18 |
// for tests to set pool protocol fees |
||
| 19 |
function setProtocolFeeForPool(PoolId id, uint24 fee) external {
|
||
| 20 |
protocolFee[id] = fee; |
||
| 21 |
} |
||
| 22 |
} |
||
| 23 | |||
| 24 |
/// @notice Reverts on call |
||
| 25 |
√ 17
|
contract RevertingProtocolFeeControllerTest is IProtocolFeeController {
|
|
| 26 |
function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
|
||
| 27 |
revert(); |
||
| 28 |
} |
||
| 29 |
} |
||
| 30 | |||
| 31 |
/// @notice Returns an out of bounds protocol fee |
||
| 32 |
√ 17
|
contract OutOfBoundsProtocolFeeControllerTest is IProtocolFeeController {
|
|
| 33 |
function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
|
||
| 34 |
// set both protocol fees to 1001, which is greater than MAX_PROTOCOL_FEE |
||
| 35 |
return (1001 << 12) | 1001; |
||
| 36 |
} |
||
| 37 |
} |
||
| 38 | |||
| 39 |
/// @notice Return a value that overflows a uint24 |
||
| 40 |
√ 17
|
contract OverflowProtocolFeeControllerTest is IProtocolFeeController {
|
|
| 41 |
function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
|
||
| 42 |
assembly {
|
||
| 43 |
let ptr := mload(0x40) |
||
| 44 |
mstore(ptr, 0xFFFFAAA001) |
||
| 45 |
return(ptr, 0x20) |
||
| 46 |
} |
||
| 47 |
} |
||
| 48 |
} |
||
| 49 | |||
| 50 |
/// @notice Returns data that is larger than a word |
||
| 51 |
√ 17
|
contract InvalidReturnSizeProtocolFeeControllerTest is IProtocolFeeController {
|
|
| 52 |
function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
|
||
| 53 |
address a = address(1); |
||
| 54 |
assembly {
|
||
| 55 |
let ptr := mload(0x40) |
||
| 56 |
mstore(ptr, a) |
||
| 57 |
mstore(add(ptr, 0x20), a) |
||
| 58 |
return(ptr, 0x40) |
||
| 59 |
} |
||
| 60 |
} |
||
| 61 |
} |
||
| 62 |
| Lines covered: | 0 / 8 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {ProtocolFees} from "../ProtocolFees.sol";
|
||
| 5 |
import {IProtocolFeeController} from "../interfaces/IProtocolFeeController.sol";
|
||
| 6 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 7 |
import {Currency} from "../types/Currency.sol";
|
||
| 8 |
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 9 |
import {Pool} from "../libraries/Pool.sol";
|
||
| 10 |
import {Slot0} from "../types/Slot0.sol";
|
||
| 11 | |||
| 12 |
contract ProtocolFeesImplementation is ProtocolFees {
|
||
| 13 |
using PoolIdLibrary for PoolKey; |
||
| 14 | |||
| 15 |
mapping(PoolId id => Pool.State) internal _pools; |
||
| 16 | |||
| 17 |
constructor(uint256 _controllerGasLimit) ProtocolFees(_controllerGasLimit) {}
|
||
| 18 | |||
| 19 |
// Used to set the price of a pool to pretend that the pool has been initialized in order to successfully set a protocol fee |
||
| 20 |
function setPrice(PoolKey memory key, uint160 sqrtPriceX96) public {
|
||
| 21 |
Pool.State storage pool = _getPool(key.toId()); |
||
| 22 |
pool.slot0 = pool.slot0.setSqrtPriceX96(sqrtPriceX96); |
||
| 23 |
} |
||
| 24 | |||
| 25 |
function _getPool(PoolId id) internal view override returns (Pool.State storage) {
|
||
| 26 |
return _pools[id]; |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function fetchProtocolFee(PoolKey memory key) public returns (bool, uint24) {
|
||
| 30 |
return ProtocolFees._fetchProtocolFee(key); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function updateProtocolFees(Currency currency, uint256 amount) public {
|
||
| 34 |
ProtocolFees._updateProtocolFees(currency, amount); |
||
| 35 |
} |
||
| 36 |
} |
||
| 37 |
| Lines covered: | 0 / 66 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: BUSL-1.1 |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {Pool} from "../libraries/Pool.sol";
|
||
| 6 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 7 |
import {Position} from "../libraries/Position.sol";
|
||
| 8 |
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
|
||
| 9 |
import {Currency, CurrencyLibrary} from "../types/Currency.sol";
|
||
| 10 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 11 |
import {TickMath} from "../libraries/TickMath.sol";
|
||
| 12 |
import {NoDelegateCall} from "../NoDelegateCall.sol";
|
||
| 13 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 14 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 15 |
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
|
||
| 16 |
import {ProtocolFees} from "../ProtocolFees.sol";
|
||
| 17 |
import {ERC6909Claims} from "../ERC6909Claims.sol";
|
||
| 18 |
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 19 |
import {BalanceDelta, BalanceDeltaLibrary, toBalanceDelta} from "../types/BalanceDelta.sol";
|
||
| 20 |
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
|
||
| 21 |
import {Lock} from "../libraries/Lock.sol";
|
||
| 22 |
import {CurrencyDelta} from "../libraries/CurrencyDelta.sol";
|
||
| 23 |
import {NonZeroDeltaCount} from "../libraries/NonZeroDeltaCount.sol";
|
||
| 24 |
import {CurrencyReserves} from "../libraries/CurrencyReserves.sol";
|
||
| 25 |
import {Extsload} from "../Extsload.sol";
|
||
| 26 |
import {Exttload} from "../Exttload.sol";
|
||
| 27 |
import {CustomRevert} from "../libraries/CustomRevert.sol";
|
||
| 28 | |||
| 29 |
/// @notice A proxy pool manager that delegates calls to the real/delegate pool manager |
||
| 30 |
contract ProxyPoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload, Exttload {
|
||
| 31 |
using PoolIdLibrary for PoolKey; |
||
| 32 |
using SafeCast for *; |
||
| 33 |
using Pool for *; |
||
| 34 |
using Hooks for IHooks; |
||
| 35 |
using Position for mapping(bytes32 => Position.Info); |
||
| 36 |
using CurrencyDelta for Currency; |
||
| 37 |
using LPFeeLibrary for uint24; |
||
| 38 |
using CurrencyReserves for Currency; |
||
| 39 |
using CustomRevert for bytes4; |
||
| 40 | |||
| 41 |
/// @inheritdoc IPoolManager |
||
| 42 |
int24 public constant MAX_TICK_SPACING = TickMath.MAX_TICK_SPACING; |
||
| 43 | |||
| 44 |
/// @inheritdoc IPoolManager |
||
| 45 |
int24 public constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING; |
||
| 46 | |||
| 47 |
mapping(PoolId id => Pool.State) internal _pools; |
||
| 48 | |||
| 49 |
address internal immutable _delegateManager; |
||
| 50 | |||
| 51 |
constructor(address delegateManager, uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {
|
||
| 52 |
_delegateManager = delegateManager; |
||
| 53 |
} |
||
| 54 | |||
| 55 |
/// @notice This will revert if the contract is locked |
||
| 56 |
modifier onlyWhenUnlocked() {
|
||
| 57 |
if (!Lock.isUnlocked()) ManagerLocked.selector.revertWith(); |
||
| 58 |
_; |
||
| 59 |
} |
||
| 60 | |||
| 61 |
/// @inheritdoc IPoolManager |
||
| 62 |
function unlock(bytes calldata data) external noDelegateCall returns (bytes memory result) {
|
||
| 63 |
if (Lock.isUnlocked()) AlreadyUnlocked.selector.revertWith(); |
||
| 64 | |||
| 65 |
Lock.unlock(); |
||
| 66 | |||
| 67 |
// the caller does everything in this callback, including paying what they owe via calls to settle |
||
| 68 |
result = IUnlockCallback(msg.sender).unlockCallback(data); |
||
| 69 | |||
| 70 |
if (NonZeroDeltaCount.read() != 0) CurrencyNotSettled.selector.revertWith(); |
||
| 71 |
Lock.lock(); |
||
| 72 |
} |
||
| 73 | |||
| 74 |
/// @inheritdoc IPoolManager |
||
| 75 |
function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) |
||
| 76 |
external |
||
| 77 |
noDelegateCall |
||
| 78 |
returns (int24 tick) |
||
| 79 |
{
|
||
| 80 |
// see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large |
||
| 81 |
if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing); |
||
| 82 |
if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing); |
||
| 83 |
if (key.currency0 >= key.currency1) {
|
||
| 84 |
CurrenciesOutOfOrderOrEqual.selector.revertWith( |
||
| 85 |
Currency.unwrap(key.currency0), Currency.unwrap(key.currency1) |
||
| 86 |
); |
||
| 87 |
} |
||
| 88 |
if (!key.hooks.isValidHookAddress(key.fee)) Hooks.HookAddressNotValid.selector.revertWith(address(key.hooks)); |
||
| 89 | |||
| 90 |
uint24 lpFee = key.fee.getInitialLPFee(); |
||
| 91 | |||
| 92 |
key.hooks.beforeInitialize(key, sqrtPriceX96, hookData); |
||
| 93 | |||
| 94 |
PoolId id = key.toId(); |
||
| 95 |
(, uint24 protocolFee) = _fetchProtocolFee(key); |
||
| 96 | |||
| 97 |
tick = _pools[id].initialize(sqrtPriceX96, protocolFee, lpFee); |
||
| 98 | |||
| 99 |
key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData); |
||
| 100 | |||
| 101 |
// emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller |
||
| 102 |
// the key's fee may be a static fee or a sentinel to denote a dynamic fee. |
||
| 103 |
emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks); |
||
| 104 |
} |
||
| 105 | |||
| 106 |
/// @inheritdoc IPoolManager |
||
| 107 |
function modifyLiquidity( |
||
| 108 |
PoolKey memory key, |
||
| 109 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 110 |
bytes calldata hookData |
||
| 111 |
) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) {
|
||
| 112 |
bytes memory result = _delegateCall( |
||
| 113 |
_delegateManager, abi.encodeWithSelector(this.modifyLiquidity.selector, key, params, hookData) |
||
| 114 |
); |
||
| 115 | |||
| 116 |
return abi.decode(result, (BalanceDelta, BalanceDelta)); |
||
| 117 |
} |
||
| 118 | |||
| 119 |
/// @inheritdoc IPoolManager |
||
| 120 |
function swap(PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData) |
||
| 121 |
external |
||
| 122 |
onlyWhenUnlocked |
||
| 123 |
noDelegateCall |
||
| 124 |
returns (BalanceDelta swapDelta) |
||
| 125 |
{
|
||
| 126 |
bytes memory result = |
||
| 127 |
_delegateCall(_delegateManager, abi.encodeWithSelector(this.swap.selector, key, params, hookData)); |
||
| 128 | |||
| 129 |
return abi.decode(result, (BalanceDelta)); |
||
| 130 |
} |
||
| 131 | |||
| 132 |
/// @inheritdoc IPoolManager |
||
| 133 |
function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) |
||
| 134 |
external |
||
| 135 |
onlyWhenUnlocked |
||
| 136 |
noDelegateCall |
||
| 137 |
returns (BalanceDelta delta) |
||
| 138 |
{
|
||
| 139 |
bytes memory result = _delegateCall( |
||
| 140 |
_delegateManager, abi.encodeWithSelector(this.donate.selector, key, amount0, amount1, hookData) |
||
| 141 |
); |
||
| 142 | |||
| 143 |
return abi.decode(result, (BalanceDelta)); |
||
| 144 |
} |
||
| 145 | |||
| 146 |
/// @inheritdoc IPoolManager |
||
| 147 |
function sync(Currency currency) public {
|
||
| 148 |
CurrencyReserves.requireNotSynced(); |
||
| 149 |
if (currency.isNative()) return; |
||
| 150 |
uint256 balance = currency.balanceOfSelf(); |
||
| 151 |
CurrencyReserves.syncCurrencyAndReserves(currency, balance); |
||
| 152 |
} |
||
| 153 | |||
| 154 |
/// @inheritdoc IPoolManager |
||
| 155 |
function take(Currency currency, address to, uint256 amount) external onlyWhenUnlocked noDelegateCall {
|
||
| 156 |
_delegateCall(_delegateManager, abi.encodeWithSelector(this.take.selector, currency, to, amount)); |
||
| 157 |
} |
||
| 158 | |||
| 159 |
/// @inheritdoc IPoolManager |
||
| 160 |
function settle() external payable onlyWhenUnlocked noDelegateCall returns (uint256 paid) {
|
||
| 161 |
bytes memory result = _delegateCall(_delegateManager, abi.encodeWithSelector(this.settle.selector)); |
||
| 162 | |||
| 163 |
return abi.decode(result, (uint256)); |
||
| 164 |
} |
||
| 165 | |||
| 166 |
/// @inheritdoc IPoolManager |
||
| 167 |
function settleFor(address recipient) external payable onlyWhenUnlocked noDelegateCall returns (uint256 paid) {
|
||
| 168 |
bytes memory result = |
||
| 169 |
_delegateCall(_delegateManager, abi.encodeWithSelector(this.settleFor.selector, recipient)); |
||
| 170 | |||
| 171 |
return abi.decode(result, (uint256)); |
||
| 172 |
} |
||
| 173 | |||
| 174 |
/// @inheritdoc IPoolManager |
||
| 175 |
function clear(Currency currency, uint256 amount) external onlyWhenUnlocked {
|
||
| 176 |
_delegateCall(_delegateManager, abi.encodeWithSelector(this.clear.selector, currency, amount)); |
||
| 177 |
} |
||
| 178 | |||
| 179 |
/// @inheritdoc IPoolManager |
||
| 180 |
function mint(address to, uint256 id, uint256 amount) external onlyWhenUnlocked noDelegateCall {
|
||
| 181 |
_delegateCall(_delegateManager, abi.encodeWithSelector(this.mint.selector, to, id, amount)); |
||
| 182 |
} |
||
| 183 | |||
| 184 |
/// @inheritdoc IPoolManager |
||
| 185 |
function burn(address from, uint256 id, uint256 amount) external onlyWhenUnlocked noDelegateCall {
|
||
| 186 |
_delegateCall(_delegateManager, abi.encodeWithSelector(this.burn.selector, from, id, amount)); |
||
| 187 |
} |
||
| 188 | |||
| 189 |
/// @inheritdoc IPoolManager |
||
| 190 |
function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external {
|
||
| 191 |
if (!key.fee.isDynamicFee() || msg.sender != address(key.hooks)) {
|
||
| 192 |
UnauthorizedDynamicLPFeeUpdate.selector.revertWith(); |
||
| 193 |
} |
||
| 194 |
newDynamicLPFee.validate(); |
||
| 195 |
PoolId id = key.toId(); |
||
| 196 |
_pools[id].setLPFee(newDynamicLPFee); |
||
| 197 |
} |
||
| 198 | |||
| 199 |
/// @notice Make a delegate call, bubble up any error or return the result |
||
| 200 |
function _delegateCall(address target, bytes memory data) internal returns (bytes memory result) {
|
||
| 201 |
(bool success, bytes memory returnData) = target.delegatecall(data); |
||
| 202 | |||
| 203 |
if (!success) {
|
||
| 204 |
if (returnData.length == 0) {
|
||
| 205 |
revert(); |
||
| 206 |
} else {
|
||
| 207 |
assembly {
|
||
| 208 |
let size := mload(returnData) |
||
| 209 |
revert(add(32, returnData), size) |
||
| 210 |
} |
||
| 211 |
} |
||
| 212 |
} |
||
| 213 | |||
| 214 |
return returnData; |
||
| 215 |
} |
||
| 216 | |||
| 217 |
/// @notice Implementation of the _getPool function defined in ProtocolFees |
||
| 218 |
function _getPool(PoolId id) internal view override returns (Pool.State storage) {
|
||
| 219 |
return _pools[id]; |
||
| 220 |
} |
||
| 221 |
} |
||
| 222 |
| Lines covered: | 0 / 77 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 5 |
import {BaseTestHooks} from "./BaseTestHooks.sol";
|
||
| 6 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 7 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 8 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 10 |
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
|
||
| 11 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 12 |
import {Currency} from "../types/Currency.sol";
|
||
| 13 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 14 |
import {Constants} from "../../test/utils/Constants.sol";
|
||
| 15 |
import {Test} from "forge-std/Test.sol";
|
||
| 16 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 17 |
import {StateLibrary} from "../libraries/StateLibrary.sol";
|
||
| 18 |
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
|
||
| 19 |
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
|
||
| 20 | |||
| 21 |
contract SkipCallsTestHook is BaseTestHooks, Test {
|
||
| 22 |
using CurrencySettler for Currency; |
||
| 23 |
using PoolIdLibrary for PoolKey; |
||
| 24 |
using Hooks for IHooks; |
||
| 25 |
using StateLibrary for IPoolManager; |
||
| 26 |
using TransientStateLibrary for IPoolManager; |
||
| 27 | |||
| 28 |
uint256 public counter; |
||
| 29 |
IPoolManager manager; |
||
| 30 | |||
| 31 |
function setManager(IPoolManager _manager) external {
|
||
| 32 |
manager = _manager; |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function beforeInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, bytes calldata hookData) |
||
| 36 |
external |
||
| 37 |
override |
||
| 38 |
returns (bytes4) |
||
| 39 |
{
|
||
| 40 |
counter++; |
||
| 41 |
_initialize(key, sqrtPriceX96, hookData); |
||
| 42 |
return IHooks.beforeInitialize.selector; |
||
| 43 |
} |
||
| 44 | |||
| 45 |
function afterInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, int24, bytes calldata hookData) |
||
| 46 |
external |
||
| 47 |
override |
||
| 48 |
returns (bytes4) |
||
| 49 |
{
|
||
| 50 |
counter++; |
||
| 51 |
_initialize(key, sqrtPriceX96, hookData); |
||
| 52 |
return IHooks.afterInitialize.selector; |
||
| 53 |
} |
||
| 54 | |||
| 55 |
function beforeAddLiquidity( |
||
| 56 |
address, |
||
| 57 |
PoolKey calldata key, |
||
| 58 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 59 |
bytes calldata hookData |
||
| 60 |
) external override returns (bytes4) {
|
||
| 61 |
counter++; |
||
| 62 |
_addLiquidity(key, params, hookData); |
||
| 63 |
return IHooks.beforeAddLiquidity.selector; |
||
| 64 |
} |
||
| 65 | |||
| 66 |
function afterAddLiquidity( |
||
| 67 |
address, |
||
| 68 |
PoolKey calldata key, |
||
| 69 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 70 |
BalanceDelta, |
||
| 71 |
bytes calldata hookData |
||
| 72 |
) external override returns (bytes4, BalanceDelta) {
|
||
| 73 |
counter++; |
||
| 74 |
_addLiquidity(key, params, hookData); |
||
| 75 |
return (IHooks.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA); |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function beforeRemoveLiquidity( |
||
| 79 |
address, |
||
| 80 |
PoolKey calldata key, |
||
| 81 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 82 |
bytes calldata hookData |
||
| 83 |
) external override returns (bytes4) {
|
||
| 84 |
counter++; |
||
| 85 |
_removeLiquidity(key, params, hookData); |
||
| 86 |
return IHooks.beforeRemoveLiquidity.selector; |
||
| 87 |
} |
||
| 88 | |||
| 89 |
function afterRemoveLiquidity( |
||
| 90 |
address, |
||
| 91 |
PoolKey calldata key, |
||
| 92 |
IPoolManager.ModifyLiquidityParams calldata params, |
||
| 93 |
BalanceDelta, |
||
| 94 |
bytes calldata hookData |
||
| 95 |
) external override returns (bytes4, BalanceDelta) {
|
||
| 96 |
counter++; |
||
| 97 |
_removeLiquidity(key, params, hookData); |
||
| 98 |
return (IHooks.afterRemoveLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA); |
||
| 99 |
} |
||
| 100 | |||
| 101 |
function beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData) |
||
| 102 |
external |
||
| 103 |
override |
||
| 104 |
returns (bytes4, BeforeSwapDelta, uint24) |
||
| 105 |
{
|
||
| 106 |
counter++; |
||
| 107 |
_swap(key, params, hookData); |
||
| 108 |
return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0); |
||
| 109 |
} |
||
| 110 | |||
| 111 |
function afterSwap( |
||
| 112 |
address, |
||
| 113 |
PoolKey calldata key, |
||
| 114 |
IPoolManager.SwapParams calldata params, |
||
| 115 |
BalanceDelta, |
||
| 116 |
bytes calldata hookData |
||
| 117 |
) external override returns (bytes4, int128) {
|
||
| 118 |
counter++; |
||
| 119 |
_swap(key, params, hookData); |
||
| 120 |
return (IHooks.afterSwap.selector, 0); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function beforeDonate(address, PoolKey calldata key, uint256 amt0, uint256 amt1, bytes calldata hookData) |
||
| 124 |
external |
||
| 125 |
override |
||
| 126 |
returns (bytes4) |
||
| 127 |
{
|
||
| 128 |
counter++; |
||
| 129 |
_donate(key, amt0, amt1, hookData); |
||
| 130 |
return IHooks.beforeDonate.selector; |
||
| 131 |
} |
||
| 132 | |||
| 133 |
function afterDonate(address, PoolKey calldata key, uint256 amt0, uint256 amt1, bytes calldata hookData) |
||
| 134 |
external |
||
| 135 |
override |
||
| 136 |
returns (bytes4) |
||
| 137 |
{
|
||
| 138 |
counter++; |
||
| 139 |
_donate(key, amt0, amt1, hookData); |
||
| 140 |
return IHooks.afterDonate.selector; |
||
| 141 |
} |
||
| 142 | |||
| 143 |
function _initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) public {
|
||
| 144 |
// initialize a new pool with different fee |
||
| 145 |
key.fee = 2000; |
||
| 146 |
IPoolManager(manager).initialize(key, sqrtPriceX96, hookData); |
||
| 147 |
} |
||
| 148 | |||
| 149 |
function _swap(PoolKey calldata key, IPoolManager.SwapParams memory params, bytes calldata hookData) public {
|
||
| 150 |
IPoolManager(manager).swap(key, params, hookData); |
||
| 151 |
address payer = abi.decode(hookData, (address)); |
||
| 152 |
int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0); |
||
| 153 |
assertEq(delta0, params.amountSpecified); |
||
| 154 |
int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1); |
||
| 155 |
assert(delta1 > 0); |
||
| 156 |
key.currency0.settle(manager, payer, uint256(-delta0), false); |
||
| 157 |
key.currency1.take(manager, payer, uint256(delta1), false); |
||
| 158 |
} |
||
| 159 | |||
| 160 |
function _addLiquidity( |
||
| 161 |
PoolKey calldata key, |
||
| 162 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 163 |
bytes calldata hookData |
||
| 164 |
) public {
|
||
| 165 |
IPoolManager(manager).modifyLiquidity(key, params, hookData); |
||
| 166 |
address payer = abi.decode(hookData, (address)); |
||
| 167 |
int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0); |
||
| 168 |
int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1); |
||
| 169 | |||
| 170 |
assert(delta0 < 0 || delta1 < 0); |
||
| 171 |
assert(!(delta0 > 0 || delta1 > 0)); |
||
| 172 | |||
| 173 |
key.currency0.settle(manager, payer, uint256(-delta0), false); |
||
| 174 |
key.currency1.settle(manager, payer, uint256(-delta1), false); |
||
| 175 |
} |
||
| 176 | |||
| 177 |
function _removeLiquidity( |
||
| 178 |
PoolKey calldata key, |
||
| 179 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 180 |
bytes calldata hookData |
||
| 181 |
) public {
|
||
| 182 |
// first hook needs to add liquidity for itself |
||
| 183 |
IPoolManager.ModifyLiquidityParams memory newParams = |
||
| 184 |
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
|
||
| 185 |
IPoolManager(manager).modifyLiquidity(key, newParams, hookData); |
||
| 186 |
// hook removes liquidity |
||
| 187 |
IPoolManager(manager).modifyLiquidity(key, params, hookData); |
||
| 188 |
address payer = abi.decode(hookData, (address)); |
||
| 189 |
int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0); |
||
| 190 |
int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1); |
||
| 191 | |||
| 192 |
assert(delta0 < 0 || delta1 < 0); |
||
| 193 |
assert(!(delta0 > 0 || delta1 > 0)); |
||
| 194 | |||
| 195 |
key.currency0.settle(manager, payer, uint256(-delta0), false); |
||
| 196 |
key.currency1.settle(manager, payer, uint256(-delta1), false); |
||
| 197 |
} |
||
| 198 | |||
| 199 |
function _donate(PoolKey calldata key, uint256 amt0, uint256 amt1, bytes calldata hookData) public {
|
||
| 200 |
IPoolManager(manager).donate(key, amt0, amt1, hookData); |
||
| 201 |
address payer = abi.decode(hookData, (address)); |
||
| 202 |
int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0); |
||
| 203 |
int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1); |
||
| 204 |
key.currency0.settle(manager, payer, uint256(-delta0), false); |
||
| 205 |
key.currency1.settle(manager, payer, uint256(-delta1), false); |
||
| 206 |
} |
||
| 207 |
} |
||
| 208 |
| Lines covered: | 0 / 84 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {FullMath} from "../libraries/FullMath.sol";
|
||
| 5 |
import {SqrtPriceMath} from "../libraries/SqrtPriceMath.sol";
|
||
| 6 |
import {FixedPoint96} from "../libraries/FixedPoint96.sol";
|
||
| 7 | |||
| 8 |
contract SqrtPriceMathEchidnaTest {
|
||
| 9 |
function mulDivRoundingUpInvariants(uint256 x, uint256 y, uint256 z) external pure {
|
||
| 10 |
unchecked {
|
||
| 11 |
require(z > 0); |
||
| 12 |
uint256 notRoundedUp = FullMath.mulDiv(x, y, z); |
||
| 13 |
uint256 roundedUp = FullMath.mulDivRoundingUp(x, y, z); |
||
| 14 |
assert(roundedUp >= notRoundedUp); |
||
| 15 |
assert(roundedUp - notRoundedUp < 2); |
||
| 16 |
if (roundedUp - notRoundedUp == 1) {
|
||
| 17 |
assert(mulmod(x, y, z) > 0); |
||
| 18 |
} else {
|
||
| 19 |
assert(mulmod(x, y, z) == 0); |
||
| 20 |
} |
||
| 21 |
} |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function getNextSqrtPriceFromInputInvariants(uint160 sqrtP, uint128 liquidity, uint256 amountIn, bool zeroForOne) |
||
| 25 |
external |
||
| 26 |
pure |
||
| 27 |
{
|
||
| 28 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, liquidity, amountIn, zeroForOne); |
||
| 29 | |||
| 30 |
if (zeroForOne) {
|
||
| 31 |
assert(sqrtQ <= sqrtP); |
||
| 32 |
assert(amountIn >= SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, true)); |
||
| 33 |
} else {
|
||
| 34 |
assert(sqrtQ >= sqrtP); |
||
| 35 |
assert(amountIn >= SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity, true)); |
||
| 36 |
} |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function getNextSqrtPriceFromOutputInvariants(uint160 sqrtP, uint128 liquidity, uint256 amountOut, bool zeroForOne) |
||
| 40 |
external |
||
| 41 |
pure |
||
| 42 |
{
|
||
| 43 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, liquidity, amountOut, zeroForOne); |
||
| 44 | |||
| 45 |
if (zeroForOne) {
|
||
| 46 |
assert(sqrtQ <= sqrtP); |
||
| 47 |
assert(amountOut <= SqrtPriceMath.getAmount1Delta(sqrtQ, sqrtP, liquidity, false)); |
||
| 48 |
} else {
|
||
| 49 |
assert(sqrtQ > 0); // this has to be true, otherwise we need another require |
||
| 50 |
assert(sqrtQ >= sqrtP); |
||
| 51 |
assert(amountOut <= SqrtPriceMath.getAmount0Delta(sqrtP, sqrtQ, liquidity, false)); |
||
| 52 |
} |
||
| 53 |
} |
||
| 54 | |||
| 55 |
function getNextSqrtPriceFromAmount0RoundingUpInvariants( |
||
| 56 |
uint160 sqrtPX96, |
||
| 57 |
uint128 liquidity, |
||
| 58 |
uint256 amount, |
||
| 59 |
bool add |
||
| 60 |
) external pure {
|
||
| 61 |
require(sqrtPX96 > 0); |
||
| 62 |
require(liquidity > 0); |
||
| 63 |
uint160 sqrtQX96 = SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amount, add); |
||
| 64 | |||
| 65 |
if (add) {
|
||
| 66 |
assert(sqrtQX96 <= sqrtPX96); |
||
| 67 |
} else {
|
||
| 68 |
assert(sqrtQX96 >= sqrtPX96); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
if (amount == 0) {
|
||
| 72 |
assert(sqrtPX96 == sqrtQX96); |
||
| 73 |
} |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function getNextSqrtPriceFromAmount1RoundingDownInvariants( |
||
| 77 |
uint160 sqrtPX96, |
||
| 78 |
uint128 liquidity, |
||
| 79 |
uint256 amount, |
||
| 80 |
bool add |
||
| 81 |
) external pure {
|
||
| 82 |
require(sqrtPX96 > 0); |
||
| 83 |
require(liquidity > 0); |
||
| 84 |
uint160 sqrtQX96 = SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amount, add); |
||
| 85 | |||
| 86 |
if (add) {
|
||
| 87 |
assert(sqrtQX96 >= sqrtPX96); |
||
| 88 |
} else {
|
||
| 89 |
assert(sqrtQX96 <= sqrtPX96); |
||
| 90 |
} |
||
| 91 | |||
| 92 |
if (amount == 0) {
|
||
| 93 |
assert(sqrtPX96 == sqrtQX96); |
||
| 94 |
} |
||
| 95 |
} |
||
| 96 | |||
| 97 |
function getAmount0DeltaInvariants(uint160 sqrtP, uint160 sqrtQ, uint128 liquidity) external pure {
|
||
| 98 |
require(sqrtP > 0 && sqrtQ > 0); |
||
| 99 | |||
| 100 |
uint256 amount0Down = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, false); |
||
| 101 |
assert(amount0Down == SqrtPriceMath.getAmount0Delta(sqrtP, sqrtQ, liquidity, false)); |
||
| 102 | |||
| 103 |
uint256 amount0Up = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, true); |
||
| 104 |
assert(amount0Up == SqrtPriceMath.getAmount0Delta(sqrtP, sqrtQ, liquidity, true)); |
||
| 105 | |||
| 106 |
assert(amount0Down <= amount0Up); |
||
| 107 |
// diff is 0 or 1 |
||
| 108 |
assert(amount0Up - amount0Down < 2); |
||
| 109 |
} |
||
| 110 | |||
| 111 |
// ensure that chained division is always equal to the full-precision case for |
||
| 112 |
// liquidity * (sqrt(P) - sqrt(Q)) / (sqrt(P) * sqrt(Q)) |
||
| 113 |
function getAmount0DeltaEquivalency(uint160 sqrtP, uint160 sqrtQ, uint128 liquidity, bool roundUp) external pure {
|
||
| 114 |
require(sqrtP >= sqrtQ); |
||
| 115 |
require(sqrtP > 0 && sqrtQ > 0); |
||
| 116 |
require((sqrtP * sqrtQ) / sqrtP == sqrtQ); |
||
| 117 | |||
| 118 |
uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; |
||
| 119 |
uint256 numerator2 = sqrtP - sqrtQ; |
||
| 120 |
uint256 denominator = uint256(sqrtP) * sqrtQ; |
||
| 121 | |||
| 122 |
uint256 safeResult = roundUp |
||
| 123 |
? FullMath.mulDivRoundingUp(numerator1, numerator2, denominator) |
||
| 124 |
: FullMath.mulDiv(numerator1, numerator2, denominator); |
||
| 125 |
uint256 fullResult = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, roundUp); |
||
| 126 | |||
| 127 |
assert(safeResult == fullResult); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
function getAmount1DeltaInvariants(uint160 sqrtP, uint160 sqrtQ, uint128 liquidity) external pure {
|
||
| 131 |
require(sqrtP > 0 && sqrtQ > 0); |
||
| 132 | |||
| 133 |
uint256 amount1Down = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity, false); |
||
| 134 |
assert(amount1Down == SqrtPriceMath.getAmount1Delta(sqrtQ, sqrtP, liquidity, false)); |
||
| 135 | |||
| 136 |
uint256 amount1Up = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity, true); |
||
| 137 |
assert(amount1Up == SqrtPriceMath.getAmount1Delta(sqrtQ, sqrtP, liquidity, true)); |
||
| 138 | |||
| 139 |
assert(amount1Down <= amount1Up); |
||
| 140 |
// diff is 0 or 1 |
||
| 141 |
assert(amount1Up - amount1Down < 2); |
||
| 142 |
} |
||
| 143 | |||
| 144 |
function getAmount0DeltaSignedInvariants(uint160 sqrtP, uint160 sqrtQ, int128 liquidity) external pure {
|
||
| 145 |
require(sqrtP > 0 && sqrtQ > 0); |
||
| 146 | |||
| 147 |
int256 amount0 = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity); |
||
| 148 |
if (liquidity < 0) assert(amount0 <= 0); |
||
| 149 |
if (liquidity > 0) {
|
||
| 150 |
if (sqrtP == sqrtQ) assert(amount0 == 0); |
||
| 151 |
else assert(amount0 > 0); |
||
| 152 |
} |
||
| 153 |
if (liquidity == 0) assert(amount0 == 0); |
||
| 154 |
} |
||
| 155 | |||
| 156 |
function getAmount1DeltaSignedInvariants(uint160 sqrtP, uint160 sqrtQ, int128 liquidity) external pure {
|
||
| 157 |
require(sqrtP > 0 && sqrtQ > 0); |
||
| 158 | |||
| 159 |
int256 amount1 = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity); |
||
| 160 |
if (liquidity < 0) assert(amount1 <= 0); |
||
| 161 |
if (liquidity > 0) {
|
||
| 162 |
if (sqrtP == sqrtQ) assert(amount1 == 0); |
||
| 163 |
else assert(amount1 > 0); |
||
| 164 |
} |
||
| 165 |
if (liquidity == 0) assert(amount1 == 0); |
||
| 166 |
} |
||
| 167 | |||
| 168 |
function getOutOfRangeMintInvariants(uint160 sqrtA, uint160 sqrtB, int128 liquidity) external pure {
|
||
| 169 |
require(sqrtA > 0 && sqrtB > 0); |
||
| 170 |
require(liquidity > 0); |
||
| 171 | |||
| 172 |
int256 amount0 = SqrtPriceMath.getAmount0Delta(sqrtA, sqrtB, liquidity); |
||
| 173 |
int256 amount1 = SqrtPriceMath.getAmount1Delta(sqrtA, sqrtB, liquidity); |
||
| 174 | |||
| 175 |
if (sqrtA == sqrtB) {
|
||
| 176 |
assert(amount0 == 0); |
||
| 177 |
assert(amount1 == 0); |
||
| 178 |
} else {
|
||
| 179 |
assert(amount0 > 0); |
||
| 180 |
assert(amount1 > 0); |
||
| 181 |
} |
||
| 182 |
} |
||
| 183 | |||
| 184 |
function getInRangeMintInvariants(uint160 sqrtLower, uint160 sqrtCurrent, uint160 sqrtUpper, int128 liquidity) |
||
| 185 |
external |
||
| 186 |
pure |
||
| 187 |
{
|
||
| 188 |
require(sqrtLower > 0); |
||
| 189 |
require(sqrtLower < sqrtUpper); |
||
| 190 |
require(sqrtLower <= sqrtCurrent && sqrtCurrent <= sqrtUpper); |
||
| 191 |
require(liquidity > 0); |
||
| 192 | |||
| 193 |
int256 amount0 = SqrtPriceMath.getAmount0Delta(sqrtCurrent, sqrtUpper, liquidity); |
||
| 194 |
int256 amount1 = SqrtPriceMath.getAmount1Delta(sqrtLower, sqrtCurrent, liquidity); |
||
| 195 | |||
| 196 |
assert(amount0 > 0 || amount1 > 0); |
||
| 197 |
} |
||
| 198 |
} |
||
| 199 |
| Lines covered: | 1 / 12 (8.3%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency} from "../types/Currency.sol";
|
||
| 5 |
import {IPoolManager} from "../interfaces/IPoolManager.sol";
|
||
| 6 |
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
|
||
| 7 |
import {PoolKey} from "../types/PoolKey.sol";
|
||
| 8 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 9 |
import {Hooks} from "../libraries/Hooks.sol";
|
||
| 10 |
import {PoolTestBase} from "./PoolTestBase.sol";
|
||
| 11 |
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
|
||
| 12 | |||
| 13 |
contract SwapRouterNoChecks is PoolTestBase {
|
||
| 14 |
using CurrencySettler for Currency; |
||
| 15 |
using Hooks for IHooks; |
||
| 16 | |||
| 17 |
√ 27
|
constructor(IPoolManager _manager) PoolTestBase(_manager) {}
|
|
| 18 | |||
| 19 |
error NoSwapOccurred(); |
||
| 20 | |||
| 21 |
struct CallbackData {
|
||
| 22 |
address sender; |
||
| 23 |
PoolKey key; |
||
| 24 |
IPoolManager.SwapParams params; |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function swap(PoolKey memory key, IPoolManager.SwapParams memory params) external payable {
|
||
| 28 |
manager.unlock(abi.encode(CallbackData(msg.sender, key, params))); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 32 |
require(msg.sender == address(manager)); |
||
| 33 | |||
| 34 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 35 | |||
| 36 |
BalanceDelta delta = manager.swap(data.key, data.params, new bytes(0)); |
||
| 37 | |||
| 38 |
if (data.params.zeroForOne) {
|
||
| 39 |
data.key.currency0.settle(manager, data.sender, uint256(int256(-delta.amount0())), false); |
||
| 40 |
data.key.currency1.take(manager, data.sender, uint256(int256(delta.amount1())), false); |
||
| 41 |
} else {
|
||
| 42 |
data.key.currency1.settle(manager, data.sender, uint256(int256(-delta.amount1())), false); |
||
| 43 |
data.key.currency0.take(manager, data.sender, uint256(int256(delta.amount0())), false); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
return ""; |
||
| 47 |
} |
||
| 48 |
} |
||
| 49 |
| Lines covered: | 0 / 31 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 5 | |||
| 6 |
contract TestERC20 is IERC20Minimal {
|
||
| 7 |
mapping(address => uint256) public override balanceOf; |
||
| 8 |
mapping(address => mapping(address => uint256)) public override allowance; |
||
| 9 | |||
| 10 |
constructor(uint256 amountToMint) {
|
||
| 11 |
mint(msg.sender, amountToMint); |
||
| 12 |
} |
||
| 13 | |||
| 14 |
function mint(address to, uint256 amount) public {
|
||
| 15 |
uint256 balanceNext = balanceOf[to] + amount; |
||
| 16 |
require(balanceNext >= amount, "overflow balance"); |
||
| 17 |
balanceOf[to] = balanceNext; |
||
| 18 |
} |
||
| 19 | |||
| 20 |
function transfer(address recipient, uint256 amount) external override returns (bool) {
|
||
| 21 |
uint256 balanceBefore = balanceOf[msg.sender]; |
||
| 22 |
require(balanceBefore >= amount, "insufficient balance"); |
||
| 23 |
balanceOf[msg.sender] = balanceBefore - amount; |
||
| 24 | |||
| 25 |
uint256 balanceRecipient = balanceOf[recipient]; |
||
| 26 |
require(balanceRecipient + amount >= balanceRecipient, "recipient balance overflow"); |
||
| 27 |
balanceOf[recipient] = balanceRecipient + amount; |
||
| 28 | |||
| 29 |
emit Transfer(msg.sender, recipient, amount); |
||
| 30 |
return true; |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function approve(address spender, uint256 amount) external override returns (bool) {
|
||
| 34 |
allowance[msg.sender][spender] = amount; |
||
| 35 |
emit Approval(msg.sender, spender, amount); |
||
| 36 |
return true; |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
|
||
| 40 |
uint256 allowanceBefore = allowance[sender][msg.sender]; |
||
| 41 |
require(allowanceBefore >= amount, "allowance insufficient"); |
||
| 42 | |||
| 43 |
allowance[sender][msg.sender] = allowanceBefore - amount; |
||
| 44 | |||
| 45 |
uint256 balanceRecipient = balanceOf[recipient]; |
||
| 46 |
require(balanceRecipient + amount >= balanceRecipient, "overflow balance recipient"); |
||
| 47 |
balanceOf[recipient] = balanceRecipient + amount; |
||
| 48 |
uint256 balanceSender = balanceOf[sender]; |
||
| 49 |
require(balanceSender >= amount, "underflow balance sender"); |
||
| 50 |
balanceOf[sender] = balanceSender - amount; |
||
| 51 | |||
| 52 |
emit Transfer(sender, recipient, amount); |
||
| 53 |
return true; |
||
| 54 |
} |
||
| 55 |
} |
||
| 56 |
| Lines covered: | 0 / 31 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 5 | |||
| 6 |
// Regular ERC20 but it doesn't return true on transfer. |
||
| 7 |
contract TestInvalidERC20 is IERC20Minimal {
|
||
| 8 |
mapping(address => uint256) public override balanceOf; |
||
| 9 |
mapping(address => mapping(address => uint256)) public override allowance; |
||
| 10 | |||
| 11 |
constructor(uint256 amountToMint) {
|
||
| 12 |
mint(msg.sender, amountToMint); |
||
| 13 |
} |
||
| 14 | |||
| 15 |
function mint(address to, uint256 amount) public {
|
||
| 16 |
uint256 balanceNext = balanceOf[to] + amount; |
||
| 17 |
require(balanceNext >= amount, "overflow balance"); |
||
| 18 |
balanceOf[to] = balanceNext; |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function transfer(address recipient, uint256 amount) external override returns (bool) {
|
||
| 22 |
uint256 balanceBefore = balanceOf[msg.sender]; |
||
| 23 |
require(balanceBefore >= amount, "insufficient balance"); |
||
| 24 |
balanceOf[msg.sender] = balanceBefore - amount; |
||
| 25 | |||
| 26 |
uint256 balanceRecipient = balanceOf[recipient]; |
||
| 27 |
require(balanceRecipient + amount >= balanceRecipient, "recipient balance overflow"); |
||
| 28 |
balanceOf[recipient] = balanceRecipient + amount; |
||
| 29 | |||
| 30 |
emit Transfer(msg.sender, recipient, amount); |
||
| 31 |
return false; // returns false even though it succeeded |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function approve(address spender, uint256 amount) external override returns (bool) {
|
||
| 35 |
allowance[msg.sender][spender] = amount; |
||
| 36 |
emit Approval(msg.sender, spender, amount); |
||
| 37 |
return false; |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
|
||
| 41 |
uint256 allowanceBefore = allowance[sender][msg.sender]; |
||
| 42 |
require(allowanceBefore >= amount, "allowance insufficient"); |
||
| 43 | |||
| 44 |
allowance[sender][msg.sender] = allowanceBefore - amount; |
||
| 45 | |||
| 46 |
uint256 balanceRecipient = balanceOf[recipient]; |
||
| 47 |
require(balanceRecipient + amount >= balanceRecipient, "overflow balance recipient"); |
||
| 48 |
balanceOf[recipient] = balanceRecipient + amount; |
||
| 49 |
uint256 balanceSender = balanceOf[sender]; |
||
| 50 |
require(balanceSender >= amount, "underflow balance sender"); |
||
| 51 |
balanceOf[sender] = balanceSender - amount; |
||
| 52 | |||
| 53 |
emit Transfer(sender, recipient, amount); |
||
| 54 |
return false; // returns false even though it succeeded |
||
| 55 |
} |
||
| 56 |
} |
||
| 57 |
| Lines covered: | 0 / 9 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {TickMath} from "../libraries/TickMath.sol";
|
||
| 5 | |||
| 6 |
contract TickMathEchidnaTest {
|
||
| 7 |
// uniqueness and increasing order |
||
| 8 |
function checkGetSqrtPriceAtTickInvariants(int24 tick) external pure {
|
||
| 9 |
uint160 price = TickMath.getSqrtPriceAtTick(tick); |
||
| 10 |
assert(TickMath.getSqrtPriceAtTick(tick - 1) < price && price < TickMath.getSqrtPriceAtTick(tick + 1)); |
||
| 11 |
assert(price >= TickMath.MIN_SQRT_PRICE); |
||
| 12 |
assert(price <= TickMath.MAX_SQRT_PRICE); |
||
| 13 |
} |
||
| 14 | |||
| 15 |
// the price is always between the returned tick and the returned tick+1 |
||
| 16 |
function checkGetTickAtSqrtPriceInvariants(uint160 price) external pure {
|
||
| 17 |
int24 tick = TickMath.getTickAtSqrtPrice(price); |
||
| 18 |
assert(price >= TickMath.getSqrtPriceAtTick(tick) && price < TickMath.getSqrtPriceAtTick(tick + 1)); |
||
| 19 |
assert(tick >= TickMath.MIN_TICK); |
||
| 20 |
assert(tick < TickMath.MAX_TICK); |
||
| 21 |
} |
||
| 22 |
} |
||
| 23 |
| Lines covered: | 0 / 16 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {TickMath} from "../libraries/TickMath.sol";
|
||
| 5 | |||
| 6 |
contract TickMathTest {
|
||
| 7 |
function getSqrtPriceAtTick(int24 tick) external pure returns (uint160) {
|
||
| 8 |
return TickMath.getSqrtPriceAtTick(tick); |
||
| 9 |
} |
||
| 10 | |||
| 11 |
function getGasCostOfGetSqrtPriceAtTick(int24 tick) external view returns (uint256) {
|
||
| 12 |
uint256 gasBefore = gasleft(); |
||
| 13 |
TickMath.getSqrtPriceAtTick(tick); |
||
| 14 |
return gasBefore - gasleft(); |
||
| 15 |
} |
||
| 16 | |||
| 17 |
function getTickAtSqrtPrice(uint160 sqrtPriceX96) external pure returns (int24) {
|
||
| 18 |
return TickMath.getTickAtSqrtPrice(sqrtPriceX96); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function getGasCostOfGetTickAtSqrtPrice(uint160 sqrtPriceX96) external view returns (uint256) {
|
||
| 22 |
uint256 gasBefore = gasleft(); |
||
| 23 |
TickMath.getTickAtSqrtPrice(sqrtPriceX96); |
||
| 24 |
return gasBefore - gasleft(); |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function MIN_SQRT_PRICE() external pure returns (uint160) {
|
||
| 28 |
return TickMath.MIN_SQRT_PRICE; |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function MAX_SQRT_PRICE() external pure returns (uint160) {
|
||
| 32 |
return TickMath.MAX_SQRT_PRICE; |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function MIN_TICK() external pure returns (int24) {
|
||
| 36 |
return TickMath.MIN_TICK; |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function MAX_TICK() external pure returns (int24) {
|
||
| 40 |
return TickMath.MAX_TICK; |
||
| 41 |
} |
||
| 42 |
} |
||
| 43 |
| Lines covered: | 0 / 44 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Pool} from "../libraries/Pool.sol";
|
||
| 5 | |||
| 6 |
contract TickOverflowSafetyEchidnaTest {
|
||
| 7 |
using Pool for Pool.State; |
||
| 8 | |||
| 9 |
int24 private constant MIN_TICK = -16; |
||
| 10 |
int24 private constant MAX_TICK = 16; |
||
| 11 | |||
| 12 |
Pool.State private pool; |
||
| 13 |
int24 private tick = 0; |
||
| 14 | |||
| 15 |
// half the cap of fee growth has happened, this can overflow |
||
| 16 |
uint256 feeGrowthGlobal0X128 = type(uint256).max / 2; |
||
| 17 |
uint256 feeGrowthGlobal1X128 = type(uint256).max / 2; |
||
| 18 | |||
| 19 |
// used to track how much total liquidity has been added. should never be negative |
||
| 20 |
int256 totalLiquidity = 0; |
||
| 21 |
// how much total growth has happened, this cannot overflow |
||
| 22 |
uint256 private totalGrowth0 = 0; |
||
| 23 |
uint256 private totalGrowth1 = 0; |
||
| 24 | |||
| 25 |
function increaseFeeGrowthGlobal0X128(uint256 amount) external {
|
||
| 26 |
require(totalGrowth0 + amount > totalGrowth0); // overflow check |
||
| 27 |
feeGrowthGlobal0X128 += amount; // overflow desired |
||
| 28 |
totalGrowth0 += amount; |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function increaseFeeGrowthGlobal1X128(uint256 amount) external {
|
||
| 32 |
require(totalGrowth1 + amount > totalGrowth1); // overflow check |
||
| 33 |
feeGrowthGlobal1X128 += amount; // overflow desired |
||
| 34 |
totalGrowth1 += amount; |
||
| 35 |
} |
||
| 36 | |||
| 37 |
function setPosition(int24 tickLower, int24 tickUpper, int128 liquidityDelta) external {
|
||
| 38 |
require(tickLower > MIN_TICK); |
||
| 39 |
require(tickUpper < MAX_TICK); |
||
| 40 |
require(tickLower < tickUpper); |
||
| 41 |
(bool flippedLower,) = pool.updateTick(tickLower, liquidityDelta, false); |
||
| 42 |
(bool flippedUpper,) = pool.updateTick(tickUpper, liquidityDelta, true); |
||
| 43 | |||
| 44 |
if (flippedLower) {
|
||
| 45 |
if (liquidityDelta < 0) {
|
||
| 46 |
assert(pool.ticks[tickLower].liquidityGross == 0); |
||
| 47 |
pool.clearTick(tickLower); |
||
| 48 |
} else {
|
||
| 49 |
assert(pool.ticks[tickLower].liquidityGross > 0); |
||
| 50 |
} |
||
| 51 |
} |
||
| 52 | |||
| 53 |
if (flippedUpper) {
|
||
| 54 |
if (liquidityDelta < 0) {
|
||
| 55 |
assert(pool.ticks[tickUpper].liquidityGross == 0); |
||
| 56 |
pool.clearTick(tickUpper); |
||
| 57 |
} else {
|
||
| 58 |
assert(pool.ticks[tickUpper].liquidityGross > 0); |
||
| 59 |
} |
||
| 60 |
} |
||
| 61 | |||
| 62 |
totalLiquidity += liquidityDelta; |
||
| 63 |
// requires should have prevented this |
||
| 64 |
assert(totalLiquidity >= 0); |
||
| 65 | |||
| 66 |
if (totalLiquidity == 0) {
|
||
| 67 |
totalGrowth0 = 0; |
||
| 68 |
totalGrowth1 = 0; |
||
| 69 |
} |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function moveToTick(int24 target) external {
|
||
| 73 |
require(target > MIN_TICK); |
||
| 74 |
require(target < MAX_TICK); |
||
| 75 |
while (tick != target) {
|
||
| 76 |
if (tick < target) {
|
||
| 77 |
if (pool.ticks[tick + 1].liquidityGross > 0) {
|
||
| 78 |
pool.crossTick(tick + 1, feeGrowthGlobal0X128, feeGrowthGlobal1X128); |
||
| 79 |
} |
||
| 80 |
tick++; |
||
| 81 |
} else {
|
||
| 82 |
if (pool.ticks[tick].liquidityGross > 0) {
|
||
| 83 |
pool.crossTick(tick, feeGrowthGlobal0X128, feeGrowthGlobal1X128); |
||
| 84 |
} |
||
| 85 |
tick--; |
||
| 86 |
} |
||
| 87 |
} |
||
| 88 |
} |
||
| 89 |
} |
||
| 90 |
| Lines covered: | 12 / 23 (52.2%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {SafeCast} from "../libraries/SafeCast.sol";
|
||
| 5 | |||
| 6 |
/// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0 |
||
| 7 |
/// and the lower 128 bits represent the amount1. |
||
| 8 |
type BalanceDelta is int256; |
||
| 9 | |||
| 10 |
using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global;
|
||
| 11 |
using BalanceDeltaLibrary for BalanceDelta global; |
||
| 12 |
using SafeCast for int256; |
||
| 13 | |||
| 14 |
function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) {
|
||
| 15 |
assembly ("memory-safe") {
|
||
| 16 |
√ 23
|
⟳ 23
|
balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1)) |
| 17 |
} |
||
| 18 |
} |
||
| 19 | |||
| 20 |
√ 1
|
⟳ 1
|
function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
|
| 21 |
int256 res0; |
||
| 22 |
int256 res1; |
||
| 23 |
assembly ("memory-safe") {
|
||
| 24 |
√ 1
|
⟳ 1
|
let a0 := sar(128, a) |
| 25 |
√ 1
|
⟳ 1
|
let a1 := signextend(15, a) |
| 26 |
√ 3
|
⟳ 3
|
let b0 := sar(128, b) |
| 27 |
√ 3
|
⟳ 3
|
let b1 := signextend(15, b) |
| 28 |
√ 2
|
⟳ 2
|
res0 := add(a0, b0) |
| 29 |
√ 1
|
⟳ 1
|
res1 := add(a1, b1) |
| 30 |
} |
||
| 31 |
√ 2
|
⟳ 2
|
return toBalanceDelta(res0.toInt128(), res1.toInt128()); |
| 32 |
} |
||
| 33 | |||
| 34 |
function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
|
||
| 35 |
int256 res0; |
||
| 36 |
int256 res1; |
||
| 37 |
assembly ("memory-safe") {
|
||
| 38 |
let a0 := sar(128, a) |
||
| 39 |
let a1 := signextend(15, a) |
||
| 40 |
let b0 := sar(128, b) |
||
| 41 |
let b1 := signextend(15, b) |
||
| 42 |
res0 := sub(a0, b0) |
||
| 43 |
res1 := sub(a1, b1) |
||
| 44 |
} |
||
| 45 |
return toBalanceDelta(res0.toInt128(), res1.toInt128()); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
|
||
| 49 |
return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
|
||
| 53 |
√ 4
|
⟳ 4
|
return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b); |
| 54 |
} |
||
| 55 | |||
| 56 |
/// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type |
||
| 57 |
library BalanceDeltaLibrary {
|
||
| 58 |
/// @notice A BalanceDelta of 0 |
||
| 59 |
BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0); |
||
| 60 | |||
| 61 |
function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) {
|
||
| 62 |
assembly ("memory-safe") {
|
||
| 63 |
√ 3
|
⟳ 3
|
_amount0 := sar(128, balanceDelta) |
| 64 |
} |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) {
|
||
| 68 |
assembly ("memory-safe") {
|
||
| 69 |
√ 3
|
⟳ 3
|
_amount1 := signextend(15, balanceDelta) |
| 70 |
} |
||
| 71 |
} |
||
| 72 |
} |
||
| 73 |
| Lines covered: | 0 / 3 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
// Return type of the beforeSwap hook. |
||
| 5 |
// Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook) |
||
| 6 |
type BeforeSwapDelta is int256; |
||
| 7 | |||
| 8 |
// Creates a BeforeSwapDelta from specified and unspecified |
||
| 9 |
function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified) |
||
| 10 |
pure |
||
| 11 |
returns (BeforeSwapDelta beforeSwapDelta) |
||
| 12 |
{
|
||
| 13 |
assembly ("memory-safe") {
|
||
| 14 |
beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified)) |
||
| 15 |
} |
||
| 16 |
} |
||
| 17 | |||
| 18 |
/// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type |
||
| 19 |
library BeforeSwapDeltaLibrary {
|
||
| 20 |
/// @notice A BeforeSwapDelta of 0 |
||
| 21 |
BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0); |
||
| 22 | |||
| 23 |
/// extracts int128 from the upper 128 bits of the BeforeSwapDelta |
||
| 24 |
/// returned by beforeSwap |
||
| 25 |
function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) {
|
||
| 26 |
assembly ("memory-safe") {
|
||
| 27 |
deltaSpecified := sar(128, delta) |
||
| 28 |
} |
||
| 29 |
} |
||
| 30 | |||
| 31 |
/// extracts int128 from the lower 128 bits of the BeforeSwapDelta |
||
| 32 |
/// returned by beforeSwap and afterSwap |
||
| 33 |
function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) {
|
||
| 34 |
assembly ("memory-safe") {
|
||
| 35 |
deltaUnspecified := signextend(15, delta) |
||
| 36 |
} |
||
| 37 |
} |
||
| 38 |
} |
||
| 39 |
| Lines covered: | 22 / 33 (66.7%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
|
||
| 5 |
import {CustomRevert} from "../libraries/CustomRevert.sol";
|
||
| 6 | |||
| 7 |
type Currency is address; |
||
| 8 | |||
| 9 |
using {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global;
|
||
| 10 |
using CurrencyLibrary for Currency global; |
||
| 11 | |||
| 12 |
function equals(Currency currency, Currency other) pure returns (bool) {
|
||
| 13 |
return Currency.unwrap(currency) == Currency.unwrap(other); |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function greaterThan(Currency currency, Currency other) pure returns (bool) {
|
||
| 17 |
return Currency.unwrap(currency) > Currency.unwrap(other); |
||
| 18 |
} |
||
| 19 | |||
| 20 |
function lessThan(Currency currency, Currency other) pure returns (bool) {
|
||
| 21 |
return Currency.unwrap(currency) < Currency.unwrap(other); |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) {
|
||
| 25 |
√ 7
|
⟳ 7
|
return Currency.unwrap(currency) >= Currency.unwrap(other); |
| 26 |
} |
||
| 27 | |||
| 28 |
/// @title CurrencyLibrary |
||
| 29 |
/// @dev This library allows for transferring and holding native tokens and ERC20 tokens |
||
| 30 |
library CurrencyLibrary {
|
||
| 31 |
using CustomRevert for bytes4; |
||
| 32 | |||
| 33 |
/// @notice Thrown when a native transfer fails |
||
| 34 |
/// @param revertReason bubbled up revert reason |
||
| 35 |
error NativeTransferFailed(bytes revertReason); |
||
| 36 | |||
| 37 |
/// @notice Thrown when an ERC20 transfer fails |
||
| 38 |
/// @param revertReason bubbled up revert reason |
||
| 39 |
error ERC20TransferFailed(bytes revertReason); |
||
| 40 | |||
| 41 |
/// @notice A constant to represent the native currency |
||
| 42 |
Currency public constant NATIVE = Currency.wrap(address(0)); |
||
| 43 | |||
| 44 |
function transfer(Currency currency, address to, uint256 amount) internal {
|
||
| 45 |
// altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol |
||
| 46 |
// modified custom error selectors |
||
| 47 | |||
| 48 |
√ 1
|
⟳ 1
|
bool success; |
| 49 |
√ 3
|
⟳ 3
|
if (currency.isNative()) {
|
| 50 |
assembly ("memory-safe") {
|
||
| 51 |
// Transfer the ETH and revert if it fails. |
||
| 52 |
√ 7
|
⟳ 7
|
success := call(gas(), to, amount, 0, 0, 0, 0) |
| 53 |
} |
||
| 54 |
// revert with NativeTransferFailed, containing the bubbled up error as an argument |
||
| 55 |
√ 1
|
⟳ 2
|
if (!success) NativeTransferFailed.selector.bubbleUpAndRevertWith(); |
| 56 |
} else {
|
||
| 57 |
assembly ("memory-safe") {
|
||
| 58 |
// Get a pointer to some free memory. |
||
| 59 |
√ 1
|
⟳ 1
|
let fmp := mload(0x40) |
| 60 | |||
| 61 |
// Write the abi-encoded calldata into memory, beginning with the function selector. |
||
| 62 |
√ 2
|
⟳ 2
|
mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) |
| 63 |
√ 4
|
⟳ 4
|
mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. |
| 64 |
√ 3
|
⟳ 3
|
mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. |
| 65 | |||
| 66 |
success := |
||
| 67 |
and( |
||
| 68 |
// Set success to whether the call reverted, if not we check it either |
||
| 69 |
// returned exactly 1 (can't just be non-zero data), or had no return data. |
||
| 70 |
√ 5
|
⟳ 5
|
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), |
| 71 |
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. |
||
| 72 |
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. |
||
| 73 |
// Counterintuitively, this call must be positioned second to the or() call in the |
||
| 74 |
// surrounding and() call or else returndatasize() will be zero during the computation. |
||
| 75 |
√ 7
|
⟳ 7
|
call(gas(), currency, 0, fmp, 68, 0, 32) |
| 76 |
) |
||
| 77 | |||
| 78 |
// Now clean the memory we used |
||
| 79 |
√ 2
|
⟳ 2
|
mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here |
| 80 |
√ 3
|
⟳ 3
|
mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here |
| 81 |
√ 3
|
⟳ 3
|
mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here |
| 82 |
} |
||
| 83 |
// revert with ERC20TransferFailed, containing the bubbled up error as an argument |
||
| 84 |
√ 1
|
⟳ 2
|
if (!success) ERC20TransferFailed.selector.bubbleUpAndRevertWith(); |
| 85 |
} |
||
| 86 |
} |
||
| 87 | |||
| 88 |
√ 1
|
⟳ 1
|
function balanceOfSelf(Currency currency) internal view returns (uint256) {
|
| 89 |
√ 3
|
⟳ 3
|
if (currency.isNative()) {
|
| 90 |
return address(this).balance; |
||
| 91 |
} else {
|
||
| 92 |
√ 7
|
⟳ 7
|
return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this)); |
| 93 |
} |
||
| 94 |
} |
||
| 95 | |||
| 96 |
function balanceOf(Currency currency, address owner) internal view returns (uint256) {
|
||
| 97 |
if (currency.isNative()) {
|
||
| 98 |
return owner.balance; |
||
| 99 |
} else {
|
||
| 100 |
return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner); |
||
| 101 |
} |
||
| 102 |
} |
||
| 103 | |||
| 104 |
function isNative(Currency currency) internal pure returns (bool) {
|
||
| 105 |
√ 4
|
⟳ 4
|
return Currency.unwrap(currency) == Currency.unwrap(NATIVE); |
| 106 |
} |
||
| 107 | |||
| 108 |
√ 1
|
⟳ 1
|
function isZero(Currency currency) internal pure returns (bool) {
|
| 109 |
√ 1
|
⟳ 1
|
return isNative(currency); |
| 110 |
} |
||
| 111 | |||
| 112 |
function toId(Currency currency) internal pure returns (uint256) {
|
||
| 113 |
√ 18
|
⟳ 24
|
return uint160(Currency.unwrap(currency)); |
| 114 |
} |
||
| 115 | |||
| 116 |
// If the upper 12 bytes are non-zero, they will be zero-ed out |
||
| 117 |
// Therefore, fromId() and toId() are not inverses of each other |
||
| 118 |
function fromId(uint256 id) internal pure returns (Currency) {
|
||
| 119 |
return Currency.wrap(address(uint160(id))); |
||
| 120 |
} |
||
| 121 |
} |
||
| 122 |
| Lines covered: | 1 / 2 (50.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {PoolKey} from "./PoolKey.sol";
|
||
| 5 | |||
| 6 |
type PoolId is bytes32; |
||
| 7 | |||
| 8 |
/// @notice Library for computing the ID of a pool |
||
| 9 |
library PoolIdLibrary {
|
||
| 10 |
/// @notice Returns value equal to keccak256(abi.encode(poolKey)) |
||
| 11 |
function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {
|
||
| 12 |
assembly ("memory-safe") {
|
||
| 13 |
√ 6
|
⟳ 6
|
poolId := keccak256(poolKey, mul(32, 5)) |
| 14 |
} |
||
| 15 |
} |
||
| 16 |
} |
||
| 17 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {Currency} from "./Currency.sol";
|
||
| 5 |
import {IHooks} from "../interfaces/IHooks.sol";
|
||
| 6 | |||
| 7 |
/// @notice Returns the key for identifying a pool |
||
| 8 |
struct PoolKey {
|
||
| 9 |
/// @notice The lower currency of the pool, sorted numerically |
||
| 10 |
Currency currency0; |
||
| 11 |
/// @notice The higher currency of the pool, sorted numerically |
||
| 12 |
Currency currency1; |
||
| 13 |
/// @notice The pool swap fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000 |
||
| 14 |
uint24 fee; |
||
| 15 |
/// @notice Ticks that involve positions must be a multiple of tick spacing |
||
| 16 |
int24 tickSpacing; |
||
| 17 |
/// @notice The hooks of the pool |
||
| 18 |
IHooks hooks; |
||
| 19 |
} |
||
| 20 |
| Lines covered: | 8 / 12 (66.7%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
/** |
||
| 5 |
* @dev Slot0 is a packed version of solidity structure. |
||
| 6 |
* Using the packaged version saves gas by not storing the structure fields in memory slots. |
||
| 7 |
* |
||
| 8 |
* Layout: |
||
| 9 |
* 24 bits empty | 24 bits lpFee | 12 bits protocolFee 1->0 | 12 bits protocolFee 0->1 | 24 bits tick | 160 bits sqrtPriceX96 |
||
| 10 |
* |
||
| 11 |
* Fields in the direction from the least significant bit: |
||
| 12 |
* |
||
| 13 |
* The current price |
||
| 14 |
* uint160 sqrtPriceX96; |
||
| 15 |
* |
||
| 16 |
* The current tick |
||
| 17 |
* int24 tick; |
||
| 18 |
* |
||
| 19 |
* Protocol fee, expressed in hundredths of a bip, upper 12 bits are for 1->0, and the lower 12 are for 0->1 |
||
| 20 |
* the maximum is 1000 - meaning the maximum protocol fee is 0.1% |
||
| 21 |
* the protocolFee is taken from the input first, then the lpFee is taken from the remaining input |
||
| 22 |
* uint24 protocolFee; |
||
| 23 |
* |
||
| 24 |
* The current LP fee of the pool. If the pool is dynamic, this does not include the dynamic fee flag. |
||
| 25 |
* uint24 lpFee; |
||
| 26 |
*/ |
||
| 27 |
type Slot0 is bytes32; |
||
| 28 | |||
| 29 |
using Slot0Library for Slot0 global; |
||
| 30 | |||
| 31 |
/// @notice Library for getting and setting values in the Slot0 type |
||
| 32 |
library Slot0Library {
|
||
| 33 |
uint160 internal constant MASK_160_BITS = 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; |
||
| 34 |
uint24 internal constant MASK_24_BITS = 0xFFFFFF; |
||
| 35 | |||
| 36 |
uint8 internal constant TICK_OFFSET = 160; |
||
| 37 |
uint8 internal constant PROTOCOL_FEE_OFFSET = 184; |
||
| 38 |
uint8 internal constant LP_FEE_OFFSET = 208; |
||
| 39 | |||
| 40 |
// #### GETTERS #### |
||
| 41 |
function sqrtPriceX96(Slot0 _packed) internal pure returns (uint160 _sqrtPriceX96) {
|
||
| 42 |
assembly ("memory-safe") {
|
||
| 43 |
_sqrtPriceX96 := and(MASK_160_BITS, _packed) |
||
| 44 |
} |
||
| 45 |
} |
||
| 46 | |||
| 47 |
function tick(Slot0 _packed) internal pure returns (int24 _tick) {
|
||
| 48 |
assembly ("memory-safe") {
|
||
| 49 |
√ 9
|
⟳ 9
|
_tick := signextend(2, shr(TICK_OFFSET, _packed)) |
| 50 |
} |
||
| 51 |
} |
||
| 52 | |||
| 53 |
function protocolFee(Slot0 _packed) internal pure returns (uint24 _protocolFee) {
|
||
| 54 |
assembly ("memory-safe") {
|
||
| 55 |
√ 1
|
⟳ 1
|
_protocolFee := and(MASK_24_BITS, shr(PROTOCOL_FEE_OFFSET, _packed)) |
| 56 |
} |
||
| 57 |
} |
||
| 58 | |||
| 59 |
function lpFee(Slot0 _packed) internal pure returns (uint24 _lpFee) {
|
||
| 60 |
assembly ("memory-safe") {
|
||
| 61 |
√ 2
|
⟳ 2
|
_lpFee := and(MASK_24_BITS, shr(LP_FEE_OFFSET, _packed)) |
| 62 |
} |
||
| 63 |
} |
||
| 64 | |||
| 65 |
// #### SETTERS #### |
||
| 66 |
function setSqrtPriceX96(Slot0 _packed, uint160 _sqrtPriceX96) internal pure returns (Slot0 _result) {
|
||
| 67 |
assembly ("memory-safe") {
|
||
| 68 |
√ 3
|
⟳ 3
|
_result := or(and(not(MASK_160_BITS), _packed), and(MASK_160_BITS, _sqrtPriceX96)) |
| 69 |
} |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function setTick(Slot0 _packed, int24 _tick) internal pure returns (Slot0 _result) {
|
||
| 73 |
assembly ("memory-safe") {
|
||
| 74 |
√ 3
|
⟳ 3
|
_result := or(and(not(shl(TICK_OFFSET, MASK_24_BITS)), _packed), shl(TICK_OFFSET, and(MASK_24_BITS, _tick))) |
| 75 |
} |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function setProtocolFee(Slot0 _packed, uint24 _protocolFee) internal pure returns (Slot0 _result) {
|
||
| 79 |
assembly ("memory-safe") {
|
||
| 80 |
_result := |
||
| 81 |
or( |
||
| 82 |
√ 1
|
⟳ 1
|
and(not(shl(PROTOCOL_FEE_OFFSET, MASK_24_BITS)), _packed), |
| 83 |
√ 2
|
⟳ 2
|
shl(PROTOCOL_FEE_OFFSET, and(MASK_24_BITS, _protocolFee)) |
| 84 |
) |
||
| 85 |
} |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function setLpFee(Slot0 _packed, uint24 _lpFee) internal pure returns (Slot0 _result) {
|
||
| 89 |
assembly ("memory-safe") {
|
||
| 90 |
_result := |
||
| 91 |
√ 1
|
⟳ 1
|
or(and(not(shl(LP_FEE_OFFSET, MASK_24_BITS)), _packed), shl(LP_FEE_OFFSET, and(MASK_24_BITS, _lpFee))) |
| 92 |
} |
||
| 93 |
} |
||
| 94 |
} |
||
| 95 |
| Lines covered: | 0 / 20 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {CurrencyReserves} from "../src/libraries/CurrencyReserves.sol";
|
||
| 5 |
import {Test} from "forge-std/Test.sol";
|
||
| 6 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 7 | |||
| 8 |
contract CurrencyReservesTest is Test {
|
||
| 9 |
using CurrencyReserves for Currency; |
||
| 10 | |||
| 11 |
Currency currency0; |
||
| 12 | |||
| 13 |
function setUp() public {
|
||
| 14 |
currency0 = Currency.wrap(address(0xbeef)); |
||
| 15 |
} |
||
| 16 | |||
| 17 |
function test_getReserves_returns_set() public {
|
||
| 18 |
currency0.syncCurrencyAndReserves(100); |
||
| 19 |
uint256 value = CurrencyReserves.getSyncedReserves(); |
||
| 20 |
assertEq(value, 100); |
||
| 21 |
assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency0)); |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function test_set_twice_returns_correct_value() public {
|
||
| 25 |
currency0.syncCurrencyAndReserves(100); |
||
| 26 |
currency0.syncCurrencyAndReserves(200); |
||
| 27 |
uint256 value = CurrencyReserves.getSyncedReserves(); |
||
| 28 |
assertEq(value, 200); |
||
| 29 |
assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency0)); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function test_reset_currency() public {
|
||
| 33 |
currency0.syncCurrencyAndReserves(100); |
||
| 34 |
uint256 value = CurrencyReserves.getSyncedReserves(); |
||
| 35 |
assertEq(value, 100); |
||
| 36 |
assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency0)); |
||
| 37 |
CurrencyReserves.resetCurrency(); |
||
| 38 |
uint256 valueAfterReset = CurrencyReserves.getSyncedReserves(); |
||
| 39 |
assertEq(valueAfterReset, 100); |
||
| 40 |
assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), address(0)); |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_reservesOfSlot() public pure {
|
||
| 44 |
assertEq(bytes32(uint256(keccak256("ReservesOf")) - 1), CurrencyReserves.RESERVES_OF_SLOT);
|
||
| 45 |
} |
||
| 46 | |||
| 47 |
function test_syncSlot() public pure {
|
||
| 48 |
assertEq(bytes32(uint256(keccak256("Currency")) - 1), CurrencyReserves.CURRENCY_SLOT);
|
||
| 49 |
} |
||
| 50 | |||
| 51 |
function test_fuzz_get_set(Currency currency, uint256 value) public {
|
||
| 52 |
vm.assume(value != type(uint256).max); |
||
| 53 |
currency.syncCurrencyAndReserves(value); |
||
| 54 | |||
| 55 |
assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency)); |
||
| 56 |
assertEq(CurrencyReserves.getSyncedReserves(), value); |
||
| 57 |
} |
||
| 58 |
} |
||
| 59 |
| Lines covered: | 0 / 139 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 6 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 7 |
import {FeeTakingHook} from "../src/test/FeeTakingHook.sol";
|
||
| 8 |
import {CustomCurveHook} from "../src/test/CustomCurveHook.sol";
|
||
| 9 |
import {DeltaReturningHook} from "../src/test/DeltaReturningHook.sol";
|
||
| 10 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 11 |
import {Hooks} from "../src/libraries/Hooks.sol";
|
||
| 12 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 13 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 14 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 15 |
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
|
||
| 16 |
import {SafeCast} from "../src/libraries/SafeCast.sol";
|
||
| 17 | |||
| 18 |
contract CustomAccountingTest is Test, Deployers, GasSnapshot {
|
||
| 19 |
using SafeCast for *; |
||
| 20 | |||
| 21 |
address hook; |
||
| 22 | |||
| 23 |
function setUp() public {
|
||
| 24 |
initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0))); |
||
| 25 |
} |
||
| 26 | |||
| 27 |
function _setUpDeltaReturnFuzzPool() internal {
|
||
| 28 |
address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 29 |
address impl = address(new DeltaReturningHook(manager)); |
||
| 30 |
_etchHookAndInitPool(hookAddr, impl); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function _setUpCustomCurvePool() internal {
|
||
| 34 |
address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 35 |
address impl = address(new CustomCurveHook(manager)); |
||
| 36 |
_etchHookAndInitPool(hookAddr, impl); |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function _setUpFeeTakingPool() internal {
|
||
| 40 |
address hookAddr = address( |
||
| 41 |
uint160( |
||
| 42 |
Hooks.AFTER_SWAP_FLAG | Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG |
||
| 43 |
| Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG |
||
| 44 |
| Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG |
||
| 45 |
) |
||
| 46 |
); |
||
| 47 |
address impl = address(new FeeTakingHook(manager)); |
||
| 48 |
_etchHookAndInitPool(hookAddr, impl); |
||
| 49 |
} |
||
| 50 | |||
| 51 |
function _etchHookAndInitPool(address hookAddr, address implAddr) internal {
|
||
| 52 |
vm.etch(hookAddr, implAddr.code); |
||
| 53 |
hook = hookAddr; |
||
| 54 | |||
| 55 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(hookAddr), 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 56 |
} |
||
| 57 | |||
| 58 |
// ------------------------ SWAP ------------------------ |
||
| 59 | |||
| 60 |
function test_swap_afterSwapFeeOnUnspecified_exactInput() public {
|
||
| 61 |
_setUpFeeTakingPool(); |
||
| 62 |
uint256 balanceBefore0 = currency0.balanceOf(address(this)); |
||
| 63 |
uint256 balanceBefore1 = currency1.balanceOf(address(this)); |
||
| 64 | |||
| 65 |
uint256 amountToSwap = 1000; |
||
| 66 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 67 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 68 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 69 |
zeroForOne: true, |
||
| 70 |
amountSpecified: -int256(amountToSwap), |
||
| 71 |
sqrtPriceLimitX96: SQRT_PRICE_1_2 |
||
| 72 |
}); |
||
| 73 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 74 |
snapLastCall("swap CA fee on unspecified");
|
||
| 75 | |||
| 76 |
// input is 1000 for output of 998 with this much liquidity available |
||
| 77 |
// plus a fee of 1.23% on unspecified (output) => (998*123)/10000 = 12 |
||
| 78 |
assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amountToSwap, "amount 0"); |
||
| 79 |
assertEq(currency1.balanceOf(address(this)), balanceBefore1 + (998 - 12), "amount 1"); |
||
| 80 |
} |
||
| 81 | |||
| 82 |
function test_swap_afterSwapFeeOnUnspecified_exactOutput() public {
|
||
| 83 |
_setUpFeeTakingPool(); |
||
| 84 | |||
| 85 |
uint256 balanceBefore0 = currency0.balanceOf(address(this)); |
||
| 86 |
uint256 balanceBefore1 = currency1.balanceOf(address(this)); |
||
| 87 | |||
| 88 |
uint256 amountToSwap = 1000; |
||
| 89 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 90 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 91 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 92 |
zeroForOne: true, |
||
| 93 |
amountSpecified: int256(amountToSwap), |
||
| 94 |
sqrtPriceLimitX96: SQRT_PRICE_1_2 |
||
| 95 |
}); |
||
| 96 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 97 | |||
| 98 |
// input is 1002 for output of 1000 with this much liquidity available |
||
| 99 |
// plus a fee of 1.23% on unspecified (input) => (1002*123)/10000 = 12 |
||
| 100 |
assertEq(currency0.balanceOf(address(this)), balanceBefore0 - 1002 - 12, "amount 0"); |
||
| 101 |
assertEq(currency1.balanceOf(address(this)), balanceBefore1 + amountToSwap, "amount 1"); |
||
| 102 |
} |
||
| 103 | |||
| 104 |
function test_swap_beforeSwapNoOpsSwap_exactInput() public {
|
||
| 105 |
_setUpCustomCurvePool(); |
||
| 106 | |||
| 107 |
// add liquidity by sending tokens straight into the contract |
||
| 108 |
key.currency0.transfer(hook, 10e18); |
||
| 109 |
key.currency1.transfer(hook, 10e18); |
||
| 110 | |||
| 111 |
uint256 balanceBefore0 = currency0.balanceOf(address(this)); |
||
| 112 |
uint256 balanceBefore1 = currency1.balanceOf(address(this)); |
||
| 113 | |||
| 114 |
uint256 amountToSwap = 123456; |
||
| 115 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 116 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 117 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 118 |
zeroForOne: true, |
||
| 119 |
amountSpecified: -int256(amountToSwap), |
||
| 120 |
sqrtPriceLimitX96: SQRT_PRICE_1_2 |
||
| 121 |
}); |
||
| 122 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 123 |
snapLastCall("swap CA custom curve + swap noop");
|
||
| 124 | |||
| 125 |
// the custom curve hook is 1-1 linear |
||
| 126 |
assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amountToSwap, "amount 0"); |
||
| 127 |
assertEq(currency1.balanceOf(address(this)), balanceBefore1 + amountToSwap, "amount 1"); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
function test_swap_beforeSwapNoOpsSwap_exactOutput() public {
|
||
| 131 |
_setUpCustomCurvePool(); |
||
| 132 | |||
| 133 |
// add liquidity by sending tokens straight into the contract |
||
| 134 |
key.currency0.transfer(hook, 10e18); |
||
| 135 |
key.currency1.transfer(hook, 10e18); |
||
| 136 | |||
| 137 |
uint256 balanceBefore0 = currency0.balanceOf(address(this)); |
||
| 138 |
uint256 balanceBefore1 = currency1.balanceOf(address(this)); |
||
| 139 | |||
| 140 |
uint256 amountToSwap = 123456; |
||
| 141 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 142 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 143 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 144 |
zeroForOne: true, |
||
| 145 |
amountSpecified: int256(amountToSwap), |
||
| 146 |
sqrtPriceLimitX96: SQRT_PRICE_1_2 |
||
| 147 |
}); |
||
| 148 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 149 | |||
| 150 |
// the custom curve hook is 1-1 linear |
||
| 151 |
assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amountToSwap, "amount 0"); |
||
| 152 |
assertEq(currency1.balanceOf(address(this)), balanceBefore1 + amountToSwap, "amount 1"); |
||
| 153 |
} |
||
| 154 | |||
| 155 |
// maximum available liquidity in each direction for the pool in test_fuzz_swap_beforeSwap_returnsDeltaSpecified |
||
| 156 |
int128 maxPossibleIn_fuzz_test = -6018336102428409; |
||
| 157 |
int128 maxPossibleOut_fuzz_test = 5981737760509662; |
||
| 158 | |||
| 159 |
function test_fuzz_swap_beforeSwap_returnsDeltaSpecified( |
||
| 160 |
int128 hookDeltaSpecified, |
||
| 161 |
int256 amountSpecified, |
||
| 162 |
bool zeroForOne |
||
| 163 |
) public {
|
||
| 164 |
// ------------------------ SETUP ------------------------ |
||
| 165 |
Currency specifiedCurrency; |
||
| 166 |
bool isExactIn; |
||
| 167 |
_setUpDeltaReturnFuzzPool(); |
||
| 168 | |||
| 169 |
// initialize the pool and give the hook tokens to pay into swaps |
||
| 170 |
key.currency0.transfer(hook, type(uint128).max); |
||
| 171 |
key.currency1.transfer(hook, type(uint128).max); |
||
| 172 | |||
| 173 |
// bound amount specified to be a fair amount less than the amount of liquidity we have |
||
| 174 |
amountSpecified = int128(bound(amountSpecified, -3e11, 3e11)); |
||
| 175 |
isExactIn = amountSpecified < 0; |
||
| 176 |
specifiedCurrency = (isExactIn == zeroForOne) ? key.currency0 : key.currency1; |
||
| 177 | |||
| 178 |
// bound delta in specified to not take more than the reserves available, nor be the minimum int to |
||
| 179 |
// stop the hook reverting on take/settle |
||
| 180 |
uint128 reservesOfSpecified = uint128(specifiedCurrency.balanceOf(address(manager))); |
||
| 181 |
hookDeltaSpecified = int128(bound(hookDeltaSpecified, type(int128).min + 1, int128(reservesOfSpecified))); |
||
| 182 |
DeltaReturningHook(hook).setDeltaSpecified(hookDeltaSpecified); |
||
| 183 | |||
| 184 |
// setup swap variables |
||
| 185 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 186 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 187 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 188 |
zeroForOne: zeroForOne, |
||
| 189 |
amountSpecified: amountSpecified, |
||
| 190 |
sqrtPriceLimitX96: (zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT) |
||
| 191 |
}); |
||
| 192 | |||
| 193 |
// ------------------------ FUZZING CASES ------------------------ |
||
| 194 |
// with an amount specified of 0: the trade reverts |
||
| 195 |
if (amountSpecified == 0) {
|
||
| 196 |
vm.expectRevert(IPoolManager.SwapAmountCannotBeZero.selector); |
||
| 197 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 198 | |||
| 199 |
// trade is exact input of n:, the hook cannot TAKE (+ve hookDeltaSpecified) more than n in input |
||
| 200 |
// otherwise the user would have to send more than n in input |
||
| 201 |
} else if (isExactIn && (hookDeltaSpecified > -amountSpecified)) {
|
||
| 202 |
vm.expectRevert(Hooks.HookDeltaExceedsSwapAmount.selector); |
||
| 203 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 204 | |||
| 205 |
// exact output of n: the hook cannot GIVE (-ve hookDeltaSpecified) more than n in output |
||
| 206 |
// otherwise the user would receive more than n in output |
||
| 207 |
} else if (!isExactIn && (amountSpecified < -hookDeltaSpecified)) {
|
||
| 208 |
vm.expectRevert(Hooks.HookDeltaExceedsSwapAmount.selector); |
||
| 209 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 210 | |||
| 211 |
// successful swaps ! |
||
| 212 |
} else {
|
||
| 213 |
uint256 balanceThisBefore = specifiedCurrency.balanceOf(address(this)); |
||
| 214 |
uint256 balanceHookBefore = specifiedCurrency.balanceOf(hook); |
||
| 215 |
uint256 balanceManagerBefore = specifiedCurrency.balanceOf(address(manager)); |
||
| 216 | |||
| 217 |
BalanceDelta delta = swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 218 |
int128 deltaSpecified = (zeroForOne == isExactIn) ? delta.amount0() : delta.amount1(); |
||
| 219 | |||
| 220 |
// in all cases the hook gets what they took, and the user gets the swap's output delta (checked more below) |
||
| 221 |
assertEq( |
||
| 222 |
balanceHookBefore.toInt256() + hookDeltaSpecified, |
||
| 223 |
specifiedCurrency.balanceOf(hook).toInt256(), |
||
| 224 |
"hook balance change incorrect" |
||
| 225 |
); |
||
| 226 |
assertEq( |
||
| 227 |
balanceThisBefore.toInt256() + deltaSpecified, |
||
| 228 |
specifiedCurrency.balanceOf(address(this)).toInt256(), |
||
| 229 |
"swapper balance change incorrect" |
||
| 230 |
); |
||
| 231 | |||
| 232 |
// exact input, where there arent enough input reserves available to pay swap and hook |
||
| 233 |
// note: all 3 values are negative, so we use < |
||
| 234 |
if (isExactIn && (hookDeltaSpecified + amountSpecified < maxPossibleIn_fuzz_test)) {
|
||
| 235 |
// the hook will have taken hookDeltaSpecified of the maxPossibleIn |
||
| 236 |
assertEq(deltaSpecified, maxPossibleIn_fuzz_test - hookDeltaSpecified, "deltaSpecified exact input"); |
||
| 237 |
// the manager received all possible input tokens |
||
| 238 |
assertEq( |
||
| 239 |
balanceManagerBefore.toInt256() - maxPossibleIn_fuzz_test, |
||
| 240 |
specifiedCurrency.balanceOf(address(manager)).toInt256(), |
||
| 241 |
"manager balance change exact input" |
||
| 242 |
); |
||
| 243 | |||
| 244 |
// exact output, where there isnt enough output reserves available to pay swap and hook |
||
| 245 |
} else if (!isExactIn && (hookDeltaSpecified + amountSpecified > maxPossibleOut_fuzz_test)) {
|
||
| 246 |
// the hook will have taken hookDeltaSpecified of the maxPossibleOut |
||
| 247 |
assertEq(deltaSpecified, maxPossibleOut_fuzz_test - hookDeltaSpecified, "deltaSpecified exact output"); |
||
| 248 |
// the manager sent out all possible output tokens |
||
| 249 |
assertEq( |
||
| 250 |
balanceManagerBefore.toInt256() - maxPossibleOut_fuzz_test, |
||
| 251 |
specifiedCurrency.balanceOf(address(manager)).toInt256(), |
||
| 252 |
"manager balance change exact output" |
||
| 253 |
); |
||
| 254 | |||
| 255 |
// enough reserves were available, so the user got what they desired |
||
| 256 |
} else {
|
||
| 257 |
assertEq(deltaSpecified, amountSpecified, "deltaSpecified not amountSpecified"); |
||
| 258 |
assertEq( |
||
| 259 |
balanceManagerBefore.toInt256() - amountSpecified - hookDeltaSpecified, |
||
| 260 |
specifiedCurrency.balanceOf(address(manager)).toInt256(), |
||
| 261 |
"manager balance change not" |
||
| 262 |
); |
||
| 263 |
} |
||
| 264 |
} |
||
| 265 |
} |
||
| 266 | |||
| 267 |
// ------------------------ MODIFY LIQUIDITY ------------------------ |
||
| 268 | |||
| 269 |
function test_addLiquidity_withFeeTakingHook() public {
|
||
| 270 |
_setUpFeeTakingPool(); |
||
| 271 | |||
| 272 |
uint256 balanceBefore0 = currency0.balanceOf(address(this)); |
||
| 273 |
uint256 balanceBefore1 = currency1.balanceOf(address(this)); |
||
| 274 |
uint256 hookBalanceBefore0 = currency0.balanceOf(hook); |
||
| 275 |
uint256 hookBalanceBefore1 = currency1.balanceOf(hook); |
||
| 276 |
uint256 managerBalanceBefore0 = currency0.balanceOf(address(manager)); |
||
| 277 |
uint256 managerBalanceBefore1 = currency1.balanceOf(address(manager)); |
||
| 278 |
// console2.log(address(key.hooks)); |
||
| 279 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 280 |
snapLastCall("addLiquidity CA fee");
|
||
| 281 | |||
| 282 |
uint256 hookGain0 = currency0.balanceOf(hook) - hookBalanceBefore0; |
||
| 283 |
uint256 hookGain1 = currency1.balanceOf(hook) - hookBalanceBefore1; |
||
| 284 |
uint256 thisLoss0 = balanceBefore0 - currency0.balanceOf(address(this)); |
||
| 285 |
uint256 thisLoss1 = balanceBefore1 - currency1.balanceOf(address(this)); |
||
| 286 |
uint256 managerGain0 = currency0.balanceOf(address(manager)) - managerBalanceBefore0; |
||
| 287 |
uint256 managerGain1 = currency1.balanceOf(address(manager)) - managerBalanceBefore1; |
||
| 288 | |||
| 289 |
// Assert that the hook got 5.43% of the added liquidity |
||
| 290 |
assertEq(hookGain0, managerGain0 * 543 / 10000, "hook amount 0"); |
||
| 291 |
assertEq(hookGain1, managerGain1 * 543 / 10000, "hook amount 1"); |
||
| 292 |
assertEq(thisLoss0 - hookGain0, managerGain0, "manager amount 0"); |
||
| 293 |
assertEq(thisLoss1 - hookGain1, managerGain1, "manager amount 1"); |
||
| 294 |
} |
||
| 295 | |||
| 296 |
function test_removeLiquidity_withFeeTakingHook() public {
|
||
| 297 |
_setUpFeeTakingPool(); |
||
| 298 | |||
| 299 |
uint256 balanceBefore0 = currency0.balanceOf(address(this)); |
||
| 300 |
uint256 balanceBefore1 = currency1.balanceOf(address(this)); |
||
| 301 |
uint256 hookBalanceBefore0 = currency0.balanceOf(hook); |
||
| 302 |
uint256 hookBalanceBefore1 = currency1.balanceOf(hook); |
||
| 303 |
uint256 managerBalanceBefore0 = currency0.balanceOf(address(manager)); |
||
| 304 |
uint256 managerBalanceBefore1 = currency1.balanceOf(address(manager)); |
||
| 305 | |||
| 306 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 307 |
snapLastCall("removeLiquidity CA fee");
|
||
| 308 | |||
| 309 |
uint256 hookGain0 = currency0.balanceOf(hook) - hookBalanceBefore0; |
||
| 310 |
uint256 hookGain1 = currency1.balanceOf(hook) - hookBalanceBefore1; |
||
| 311 |
uint256 thisGain0 = currency0.balanceOf(address(this)) - balanceBefore0; |
||
| 312 |
uint256 thisGain1 = currency1.balanceOf(address(this)) - balanceBefore1; |
||
| 313 |
uint256 managerLoss0 = managerBalanceBefore0 - currency0.balanceOf(address(manager)); |
||
| 314 |
uint256 managerLoss1 = managerBalanceBefore1 - currency1.balanceOf(address(manager)); |
||
| 315 | |||
| 316 |
// Assert that the hook got 5.43% of the withdrawn liquidity |
||
| 317 |
assertEq(hookGain0, managerLoss0 * 543 / 10000, "hook amount 0"); |
||
| 318 |
assertEq(hookGain1, managerLoss1 * 543 / 10000, "hook amount 1"); |
||
| 319 |
assertEq(thisGain0 + hookGain0, managerLoss0, "manager amount 0"); |
||
| 320 |
assertEq(thisGain1 + hookGain1, managerLoss1, "manager amount 1"); |
||
| 321 |
} |
||
| 322 |
} |
||
| 323 |
| Lines covered: | 0 / 138 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
|
||
| 7 |
import {Hooks} from "../src/libraries/Hooks.sol";
|
||
| 8 |
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
|
||
| 9 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 10 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 11 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 12 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 13 |
import {PoolManager} from "../src/PoolManager.sol";
|
||
| 14 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 15 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 16 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 17 |
import {DynamicFeesTestHook} from "../src/test/DynamicFeesTestHook.sol";
|
||
| 18 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 19 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 20 |
import {Pool} from "../src/libraries/Pool.sol";
|
||
| 21 |
import {BalanceDelta, BalanceDeltaLibrary} from "../src/types/BalanceDelta.sol";
|
||
| 22 |
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
|
||
| 23 | |||
| 24 |
contract TestDynamicFees is Test, Deployers, GasSnapshot {
|
||
| 25 |
using StateLibrary for IPoolManager; |
||
| 26 |
using PoolIdLibrary for PoolKey; |
||
| 27 | |||
| 28 |
DynamicFeesTestHook dynamicFeesHooks = DynamicFeesTestHook( |
||
| 29 |
address( |
||
| 30 |
uint160( |
||
| 31 |
uint256(type(uint160).max) & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG |
||
| 32 |
| Hooks.AFTER_INITIALIZE_FLAG |
||
| 33 |
) |
||
| 34 |
) |
||
| 35 |
); |
||
| 36 | |||
| 37 |
DynamicFeesTestHook dynamicFeesNoHooks = |
||
| 38 |
DynamicFeesTestHook(address(uint160(uint256(type(uint160).max) & clearAllHookPermissionsMask))); |
||
| 39 | |||
| 40 |
event Swap( |
||
| 41 |
PoolId indexed poolId, |
||
| 42 |
address indexed sender, |
||
| 43 |
int128 amount0, |
||
| 44 |
int128 amount1, |
||
| 45 |
uint160 sqrtPriceX96, |
||
| 46 |
uint128 liquidity, |
||
| 47 |
int24 tick, |
||
| 48 |
uint24 fee |
||
| 49 |
); |
||
| 50 | |||
| 51 |
function setUp() public {
|
||
| 52 |
DynamicFeesTestHook impl = new DynamicFeesTestHook(); |
||
| 53 |
vm.etch(address(dynamicFeesHooks), address(impl).code); |
||
| 54 |
vm.etch(address(dynamicFeesNoHooks), address(impl).code); |
||
| 55 | |||
| 56 |
deployFreshManagerAndRouters(); |
||
| 57 |
dynamicFeesHooks.setManager(IPoolManager(manager)); |
||
| 58 |
dynamicFeesNoHooks.setManager(IPoolManager(manager)); |
||
| 59 | |||
| 60 |
deployMintAndApprove2Currencies(); |
||
| 61 |
(key,) = initPoolAndAddLiquidity( |
||
| 62 |
currency0, |
||
| 63 |
currency1, |
||
| 64 |
IHooks(address(dynamicFeesHooks)), |
||
| 65 |
LPFeeLibrary.DYNAMIC_FEE_FLAG, |
||
| 66 |
SQRT_PRICE_1_1, |
||
| 67 |
ZERO_BYTES |
||
| 68 |
); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
function test_updateDynamicLPFee_afterInitialize_failsWithTooLargeFee() public {
|
||
| 72 |
key.tickSpacing = 30; |
||
| 73 |
uint24 fee = 1000001; |
||
| 74 |
dynamicFeesHooks.setFee(fee); |
||
| 75 | |||
| 76 |
vm.expectRevert( |
||
| 77 |
abi.encodeWithSelector( |
||
| 78 |
Hooks.FailedHookCall.selector, abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee) |
||
| 79 |
) |
||
| 80 |
); |
||
| 81 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 82 |
} |
||
| 83 | |||
| 84 |
function test_initialize_initializesFeeTo0() public {
|
||
| 85 |
key.hooks = dynamicFeesNoHooks; |
||
| 86 | |||
| 87 |
// this fee is not fetched as theres no afterInitialize hook |
||
| 88 |
dynamicFeesNoHooks.setFee(1000000); |
||
| 89 | |||
| 90 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 91 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function test_updateDynamicLPFee_afterInitialize_initializesFee() public {
|
||
| 95 |
key.tickSpacing = 30; |
||
| 96 |
dynamicFeesHooks.setFee(123); |
||
| 97 | |||
| 98 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 99 |
assertEq(_fetchPoolLPFee(key), 123); |
||
| 100 |
} |
||
| 101 | |||
| 102 |
function test_updateDynamicLPFee_revertsIfCallerIsntHook() public {
|
||
| 103 |
vm.expectRevert(IPoolManager.UnauthorizedDynamicLPFeeUpdate.selector); |
||
| 104 |
manager.updateDynamicLPFee(key, 123); |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function test_updateDynamicLPFee_revertsIfPoolHasStaticFee() public {
|
||
| 108 |
key.fee = 3000; // static fee |
||
| 109 |
dynamicFeesHooks.setFee(123); |
||
| 110 | |||
| 111 |
// afterInitialize will try to update the fee, and fail |
||
| 112 |
vm.expectRevert( |
||
| 113 |
abi.encodeWithSelector( |
||
| 114 |
Hooks.FailedHookCall.selector, |
||
| 115 |
abi.encodeWithSelector(IPoolManager.UnauthorizedDynamicLPFeeUpdate.selector) |
||
| 116 |
) |
||
| 117 |
); |
||
| 118 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 119 |
} |
||
| 120 | |||
| 121 |
function test_updateDynamicLPFee_beforeSwap_failsWithTooLargeFee() public {
|
||
| 122 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 123 | |||
| 124 |
uint24 fee = 1000001; |
||
| 125 |
dynamicFeesHooks.setFee(1000001); |
||
| 126 | |||
| 127 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 128 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 129 | |||
| 130 |
vm.expectRevert( |
||
| 131 |
abi.encodeWithSelector( |
||
| 132 |
Hooks.FailedHookCall.selector, abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee) |
||
| 133 |
) |
||
| 134 |
); |
||
| 135 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 136 |
} |
||
| 137 | |||
| 138 |
function test_updateDynamicLPFee_beforeSwap_succeeds_gas() public {
|
||
| 139 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 140 | |||
| 141 |
dynamicFeesHooks.setFee(123); |
||
| 142 | |||
| 143 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 144 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 145 | |||
| 146 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 147 |
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123); |
||
| 148 | |||
| 149 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 150 |
snapLastCall("update dynamic fee in before swap");
|
||
| 151 | |||
| 152 |
assertEq(_fetchPoolLPFee(key), 123); |
||
| 153 |
} |
||
| 154 | |||
| 155 |
function test_swap_100PercentLPFee_AmountIn_NoProtocol() public {
|
||
| 156 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 157 | |||
| 158 |
dynamicFeesHooks.setFee(1000000); |
||
| 159 | |||
| 160 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 161 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 162 | |||
| 163 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 164 |
emit Swap(key.toId(), address(swapRouter), -100, 0, SQRT_PRICE_1_1, 1e18, -1, 1000000); |
||
| 165 | |||
| 166 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 167 | |||
| 168 |
assertEq(_fetchPoolLPFee(key), 1000000); |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function test_swap_50PercentLPFee_AmountIn_NoProtocol() public {
|
||
| 172 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 173 | |||
| 174 |
dynamicFeesHooks.setFee(500000); |
||
| 175 | |||
| 176 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 177 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 178 | |||
| 179 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 180 |
emit Swap(key.toId(), address(swapRouter), -100, 49, 79228162514264333632135824623, 1e18, -1, 500000); |
||
| 181 | |||
| 182 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 183 | |||
| 184 |
assertEq(_fetchPoolLPFee(key), 500000); |
||
| 185 |
} |
||
| 186 | |||
| 187 |
function test_swap_50PercentLPFee_AmountOut_NoProtocol() public {
|
||
| 188 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 189 | |||
| 190 |
dynamicFeesHooks.setFee(500000); |
||
| 191 | |||
| 192 |
IPoolManager.SwapParams memory params = |
||
| 193 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 194 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 195 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 196 | |||
| 197 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 198 |
emit Swap(key.toId(), address(swapRouter), -202, 100, 79228162514264329670727698909, 1e18, -1, 500000); |
||
| 199 | |||
| 200 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 201 | |||
| 202 |
assertEq(_fetchPoolLPFee(key), 500000); |
||
| 203 |
} |
||
| 204 | |||
| 205 |
function test_swap_revertsWith_InvalidFeeForExactOut_whenFeeIsMax() public {
|
||
| 206 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 207 | |||
| 208 |
dynamicFeesHooks.setFee(1000000); |
||
| 209 | |||
| 210 |
IPoolManager.SwapParams memory params = |
||
| 211 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 212 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 213 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 214 | |||
| 215 |
vm.expectRevert(Pool.InvalidFeeForExactOut.selector); |
||
| 216 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 217 |
} |
||
| 218 | |||
| 219 |
function test_swap_99PercentFee_AmountOut_WithProtocol() public {
|
||
| 220 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 221 | |||
| 222 |
dynamicFeesHooks.setFee(999999); |
||
| 223 | |||
| 224 |
vm.prank(address(feeController)); |
||
| 225 |
manager.setProtocolFee(key, 1000); |
||
| 226 | |||
| 227 |
IPoolManager.SwapParams memory params = |
||
| 228 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 229 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 230 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 231 | |||
| 232 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 233 |
emit Swap(key.toId(), address(swapRouter), -101000000, 100, 79228162514264329670727698909, 1e18, -1, 999999); |
||
| 234 | |||
| 235 |
BalanceDelta delta = swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 236 |
snapLastCall("swap with lp fee and protocol fee");
|
||
| 237 | |||
| 238 |
uint256 expectedProtocolFee = uint256(uint128(-delta.amount0())) * 1000 / 1e6; |
||
| 239 |
assertEq(manager.protocolFeesAccrued(currency0), expectedProtocolFee); |
||
| 240 | |||
| 241 |
assertEq(_fetchPoolLPFee(key), 999999); |
||
| 242 |
} |
||
| 243 | |||
| 244 |
function test_swap_100PercentFee_AmountIn_WithProtocol() public {
|
||
| 245 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 246 | |||
| 247 |
dynamicFeesHooks.setFee(1000000); |
||
| 248 | |||
| 249 |
vm.prank(address(feeController)); |
||
| 250 |
manager.setProtocolFee(key, 1000); |
||
| 251 | |||
| 252 |
IPoolManager.SwapParams memory params = |
||
| 253 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -1000, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 254 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 255 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 256 | |||
| 257 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 258 |
emit Swap(key.toId(), address(swapRouter), -1000, 0, SQRT_PRICE_1_1, 1e18, -1, 1000000); |
||
| 259 | |||
| 260 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 261 | |||
| 262 |
uint256 expectedProtocolFee = uint256(-params.amountSpecified) * 1000 / 1e6; |
||
| 263 |
assertEq(manager.protocolFeesAccrued(currency0), expectedProtocolFee); |
||
| 264 |
} |
||
| 265 | |||
| 266 |
function test_emitsSwapFee() public {
|
||
| 267 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 268 | |||
| 269 |
dynamicFeesHooks.setFee(123); |
||
| 270 | |||
| 271 |
vm.prank(address(feeController)); |
||
| 272 |
manager.setProtocolFee(key, 1000); |
||
| 273 | |||
| 274 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 275 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 276 | |||
| 277 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 278 |
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 1122); |
||
| 279 | |||
| 280 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 281 | |||
| 282 |
assertEq(_fetchPoolLPFee(key), 123); |
||
| 283 |
} |
||
| 284 | |||
| 285 |
function test_fuzz_ProtocolAndLPFee(uint24 lpFee, uint16 protocolFee0, uint16 protocolFee1, int256 amountSpecified) |
||
| 286 |
public |
||
| 287 |
{
|
||
| 288 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 289 | |||
| 290 |
lpFee = uint16(bound(lpFee, 0, 1000000)); |
||
| 291 |
protocolFee0 = uint16(bound(protocolFee0, 0, 1000)); |
||
| 292 |
protocolFee1 = uint16(bound(protocolFee1, 0, 1000)); |
||
| 293 |
vm.assume(amountSpecified != 0); |
||
| 294 | |||
| 295 |
uint24 protocolFee = (uint24(protocolFee1) << 12) | uint24(protocolFee0); |
||
| 296 |
dynamicFeesHooks.setFee(lpFee); |
||
| 297 | |||
| 298 |
vm.prank(address(feeController)); |
||
| 299 |
manager.setProtocolFee(key, protocolFee); |
||
| 300 | |||
| 301 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 302 |
zeroForOne: true, |
||
| 303 |
amountSpecified: amountSpecified, |
||
| 304 |
sqrtPriceLimitX96: SQRT_PRICE_1_2 |
||
| 305 |
}); |
||
| 306 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 307 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 308 | |||
| 309 |
BalanceDelta delta = swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 310 | |||
| 311 |
uint256 expectedProtocolFee = uint256(uint128(-delta.amount0())) * protocolFee0 / 1e6; |
||
| 312 |
assertEq(manager.protocolFeesAccrued(currency0), expectedProtocolFee); |
||
| 313 |
} |
||
| 314 | |||
| 315 |
function test_swap_withDynamicFee_gas() public {
|
||
| 316 |
(key,) = initPoolAndAddLiquidity( |
||
| 317 |
currency0, currency1, dynamicFeesNoHooks, LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1, ZERO_BYTES |
||
| 318 |
); |
||
| 319 | |||
| 320 |
assertEq(_fetchPoolLPFee(key), 0); |
||
| 321 |
dynamicFeesNoHooks.forcePoolFeeUpdate(key, 123); |
||
| 322 |
assertEq(_fetchPoolLPFee(key), 123); |
||
| 323 | |||
| 324 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 325 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 326 | |||
| 327 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 328 |
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123); |
||
| 329 | |||
| 330 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 331 |
snapLastCall("swap with dynamic fee");
|
||
| 332 |
} |
||
| 333 | |||
| 334 |
function _fetchPoolLPFee(PoolKey memory _key) internal view returns (uint256 lpFee) {
|
||
| 335 |
PoolId id = _key.toId(); |
||
| 336 |
(,,, lpFee) = manager.getSlot0(id); |
||
| 337 |
} |
||
| 338 |
} |
||
| 339 |
| Lines covered: | 0 / 62 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
|
||
| 7 |
import {Hooks} from "../src/libraries/Hooks.sol";
|
||
| 8 |
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
|
||
| 9 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 10 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 11 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 12 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 13 |
import {PoolManager} from "../src/PoolManager.sol";
|
||
| 14 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 15 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 16 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 17 |
import {DynamicReturnFeeTestHook} from "../src/test/DynamicReturnFeeTestHook.sol";
|
||
| 18 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 19 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 20 |
import {FullMath} from "../src/libraries/FullMath.sol";
|
||
| 21 |
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
|
||
| 22 |
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
|
||
| 23 | |||
| 24 |
contract TestDynamicReturnFees is Test, Deployers, GasSnapshot {
|
||
| 25 |
using PoolIdLibrary for PoolKey; |
||
| 26 |
using StateLibrary for IPoolManager; |
||
| 27 |
using LPFeeLibrary for uint24; |
||
| 28 | |||
| 29 |
DynamicReturnFeeTestHook dynamicReturnFeesHook = DynamicReturnFeeTestHook( |
||
| 30 |
address(uint160(uint256(type(uint160).max) & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG)) |
||
| 31 |
); |
||
| 32 | |||
| 33 |
event Swap( |
||
| 34 |
PoolId indexed poolId, |
||
| 35 |
address indexed sender, |
||
| 36 |
int128 amount0, |
||
| 37 |
int128 amount1, |
||
| 38 |
uint160 sqrtPriceX96, |
||
| 39 |
uint128 liquidity, |
||
| 40 |
int24 tick, |
||
| 41 |
uint24 fee |
||
| 42 |
); |
||
| 43 | |||
| 44 |
function setUp() public {
|
||
| 45 |
DynamicReturnFeeTestHook impl = new DynamicReturnFeeTestHook(); |
||
| 46 |
vm.etch(address(dynamicReturnFeesHook), address(impl).code); |
||
| 47 | |||
| 48 |
deployFreshManagerAndRouters(); |
||
| 49 |
dynamicReturnFeesHook.setManager(IPoolManager(manager)); |
||
| 50 | |||
| 51 |
deployMintAndApprove2Currencies(); |
||
| 52 |
(key,) = initPoolAndAddLiquidity( |
||
| 53 |
currency0, |
||
| 54 |
currency1, |
||
| 55 |
IHooks(address(dynamicReturnFeesHook)), |
||
| 56 |
LPFeeLibrary.DYNAMIC_FEE_FLAG, |
||
| 57 |
SQRT_PRICE_1_1, |
||
| 58 |
ZERO_BYTES |
||
| 59 |
); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function test_fuzz_dynamicReturnSwapFee(uint24 fee) public {
|
||
| 63 |
// hook will handle adding the override flag |
||
| 64 |
dynamicReturnFeesHook.setFee(fee); |
||
| 65 | |||
| 66 |
uint24 actualFee = fee.removeOverrideFlag(); |
||
| 67 | |||
| 68 |
int256 amountSpecified = -10000; |
||
| 69 |
BalanceDelta result; |
||
| 70 |
if (actualFee > LPFeeLibrary.MAX_LP_FEE) {
|
||
| 71 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, actualFee)); |
||
| 72 |
result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 73 |
return; |
||
| 74 |
} else {
|
||
| 75 |
result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 76 |
} |
||
| 77 |
// BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 78 |
assertEq(result.amount0(), amountSpecified); |
||
| 79 | |||
| 80 |
if (actualFee > LPFeeLibrary.MAX_LP_FEE) {
|
||
| 81 |
// if the fee is too large, the fee from beforeSwap is not used (and remains at 0 -- the default value) |
||
| 82 |
assertApproxEqAbs(uint256(int256(result.amount1())), uint256(int256(-result.amount0())), 1 wei); |
||
| 83 |
} else {
|
||
| 84 |
assertApproxEqAbs( |
||
| 85 |
uint256(int256(result.amount1())), |
||
| 86 |
FullMath.mulDiv(uint256(-amountSpecified), (1e6 - actualFee), 1e6), |
||
| 87 |
1 wei |
||
| 88 |
); |
||
| 89 |
} |
||
| 90 |
} |
||
| 91 | |||
| 92 |
function test_returnDynamicSwapFee_beforeSwap_succeeds_gas() public {
|
||
| 93 |
assertEq(_fetchPoolSwapFee(key), 0); |
||
| 94 | |||
| 95 |
dynamicReturnFeesHook.setFee(123); |
||
| 96 | |||
| 97 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 98 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 99 | |||
| 100 |
vm.expectEmit(true, true, true, true, address(manager)); |
||
| 101 |
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123); |
||
| 102 | |||
| 103 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 104 |
snapLastCall("swap with return dynamic fee");
|
||
| 105 | |||
| 106 |
assertEq(_fetchPoolSwapFee(key), 0); |
||
| 107 |
} |
||
| 108 | |||
| 109 |
function test_dynamicReturnSwapFee_initializeZeroSwapFee() public {
|
||
| 110 |
key.tickSpacing = 30; |
||
| 111 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 112 |
assertEq(_fetchPoolSwapFee(key), 0); |
||
| 113 |
} |
||
| 114 | |||
| 115 |
function test_dynamicReturnSwapFee_notUsedIfPoolIsStaticFee() public {
|
||
| 116 |
key.fee = 3000; // static fee |
||
| 117 |
dynamicReturnFeesHook.setFee(1000); // 0.10% fee is NOT used because the pool has a static fee |
||
| 118 | |||
| 119 |
initPoolAndAddLiquidity( |
||
| 120 |
currency0, currency1, IHooks(address(dynamicReturnFeesHook)), 3000, SQRT_PRICE_1_1, ZERO_BYTES |
||
| 121 |
); |
||
| 122 |
assertEq(_fetchPoolSwapFee(key), 3000); |
||
| 123 | |||
| 124 |
// despite returning a valid swap fee (1000), the static fee is used |
||
| 125 |
int256 amountSpecified = -10000; |
||
| 126 |
BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 127 | |||
| 128 |
// after swapping ~1:1, the amount out (amount1) should be approximately 0.30% less than the amount specified |
||
| 129 |
assertEq(result.amount0(), amountSpecified); |
||
| 130 |
assertApproxEqAbs( |
||
| 131 |
uint256(int256(result.amount1())), FullMath.mulDiv(uint256(-amountSpecified), (1e6 - 3000), 1e6), 1 wei |
||
| 132 |
); |
||
| 133 |
} |
||
| 134 | |||
| 135 |
function test_dynamicReturnSwapFee_notStored() public {
|
||
| 136 |
// fees returned by beforeSwap are not written to storage |
||
| 137 | |||
| 138 |
// create a new pool with an initial fee of 123 |
||
| 139 |
key.tickSpacing = 30; |
||
| 140 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 141 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 142 |
uint24 initialFee = 123; |
||
| 143 |
dynamicReturnFeesHook.forcePoolFeeUpdate(key, initialFee); |
||
| 144 |
assertEq(_fetchPoolSwapFee(key), initialFee); |
||
| 145 | |||
| 146 |
// swap with a different fee |
||
| 147 |
uint24 newFee = 3000; |
||
| 148 |
dynamicReturnFeesHook.setFee(newFee); |
||
| 149 | |||
| 150 |
int256 amountSpecified = -10000; |
||
| 151 |
BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 152 |
assertApproxEqAbs( |
||
| 153 |
uint256(int256(result.amount1())), FullMath.mulDiv(uint256(-amountSpecified), (1e6 - newFee), 1e6), 1 wei |
||
| 154 |
); |
||
| 155 | |||
| 156 |
// the fee from beforeSwap is not stored |
||
| 157 |
assertEq(_fetchPoolSwapFee(key), initialFee); |
||
| 158 |
} |
||
| 159 | |||
| 160 |
function test_dynamicReturnSwapFee_revertIfLPFeeTooLarge() public {
|
||
| 161 |
assertEq(_fetchPoolSwapFee(key), 0); |
||
| 162 | |||
| 163 |
// hook adds the override flag |
||
| 164 |
uint24 fee = 1000001; |
||
| 165 |
dynamicReturnFeesHook.setFee(fee); |
||
| 166 | |||
| 167 |
// a large fee is not used |
||
| 168 |
int256 amountSpecified = -10000; |
||
| 169 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee)); |
||
| 170 |
swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 171 |
} |
||
| 172 | |||
| 173 |
function _fetchPoolSwapFee(PoolKey memory _key) internal view returns (uint256 swapFee) {
|
||
| 174 |
PoolId id = _key.toId(); |
||
| 175 |
(,,, swapFee) = manager.getSlot0(id); |
||
| 176 |
} |
||
| 177 |
} |
||
| 178 |
| Lines covered: | 0 / 147 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.15; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 6 |
import {MockERC6909Claims} from "../src/test/MockERC6909Claims.sol";
|
||
| 7 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 8 | |||
| 9 |
contract ERC6909ClaimsTest is Test, GasSnapshot {
|
||
| 10 |
MockERC6909Claims token; |
||
| 11 | |||
| 12 |
function setUp() public {
|
||
| 13 |
token = new MockERC6909Claims(); |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function test_burnFrom_withApproval(address sender, uint256 id, uint256 mintAmount, uint256 transferAmount) |
||
| 17 |
public |
||
| 18 |
{
|
||
| 19 |
token.mint(sender, id, mintAmount); |
||
| 20 | |||
| 21 |
vm.prank(sender); |
||
| 22 |
token.approve(address(this), id, mintAmount); |
||
| 23 | |||
| 24 |
if (transferAmount > mintAmount) {
|
||
| 25 |
vm.expectRevert(); |
||
| 26 |
} |
||
| 27 |
token.burnFrom(sender, id, transferAmount); |
||
| 28 | |||
| 29 |
if (transferAmount <= mintAmount) {
|
||
| 30 |
if (mintAmount == type(uint256).max) {
|
||
| 31 |
assertEq(token.allowance(sender, address(this), id), type(uint256).max); |
||
| 32 |
} else {
|
||
| 33 |
if (sender != address(this)) {
|
||
| 34 |
assertEq(token.allowance(sender, address(this), id), mintAmount - transferAmount); |
||
| 35 |
} else {
|
||
| 36 |
assertEq(token.allowance(sender, address(this), id), mintAmount); |
||
| 37 |
} |
||
| 38 |
} |
||
| 39 |
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount); |
||
| 40 |
} |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_burnFrom_revertsWithNoApproval() public {
|
||
| 44 |
token.mint(address(this), 1337, 100); |
||
| 45 | |||
| 46 |
vm.prank(address(0xBEEF)); |
||
| 47 |
vm.expectRevert(); |
||
| 48 |
token.burnFrom(address(this), 1337, 100); |
||
| 49 |
} |
||
| 50 | |||
| 51 |
/// ---- Tests copied from solmate ---- /// |
||
| 52 | |||
| 53 |
function testMint() public {
|
||
| 54 |
token.mint(address(0xBEEF), 1337, 100); |
||
| 55 |
snapLastCall("ERC6909Claims mint");
|
||
| 56 | |||
| 57 |
assertEq(token.balanceOf(address(0xBEEF), 1337), 100); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function testBurn() public {
|
||
| 61 |
token.mint(address(0xBEEF), 1337, 100); |
||
| 62 |
vm.prank(address(0xBEEF)); |
||
| 63 |
token.burn(1337, 70); |
||
| 64 |
snapLastCall("ERC6909Claims burn");
|
||
| 65 | |||
| 66 |
assertEq(token.balanceOf(address(0xBEEF), 1337), 30); |
||
| 67 |
} |
||
| 68 | |||
| 69 |
function testSetOperator() public {
|
||
| 70 |
token.setOperator(address(0xBEEF), true); |
||
| 71 | |||
| 72 |
assertTrue(token.isOperator(address(this), address(0xBEEF))); |
||
| 73 |
} |
||
| 74 | |||
| 75 |
function testApprove() public {
|
||
| 76 |
token.approve(address(0xBEEF), 1337, 100); |
||
| 77 |
snapLastCall("ERC6909Claims approve");
|
||
| 78 | |||
| 79 |
assertEq(token.allowance(address(this), address(0xBEEF), 1337), 100); |
||
| 80 |
} |
||
| 81 | |||
| 82 |
function testTransfer() public {
|
||
| 83 |
address sender = address(0xABCD); |
||
| 84 | |||
| 85 |
token.mint(sender, 1337, 100); |
||
| 86 | |||
| 87 |
vm.prank(sender); |
||
| 88 | |||
| 89 |
token.transfer(address(0xBEEF), 1337, 70); |
||
| 90 |
snapLastCall("ERC6909Claims transfer");
|
||
| 91 | |||
| 92 |
assertEq(token.balanceOf(sender, 1337), 30); |
||
| 93 |
assertEq(token.balanceOf(address(0xBEEF), 1337), 70); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
function testTransferFromWithApproval() public {
|
||
| 97 |
address sender = address(0xABCD); |
||
| 98 |
address receiver = address(0xBEEF); |
||
| 99 | |||
| 100 |
token.mint(sender, 1337, 100); |
||
| 101 | |||
| 102 |
vm.prank(sender); |
||
| 103 |
token.approve(address(this), 1337, 100); |
||
| 104 | |||
| 105 |
token.transferFrom(sender, receiver, 1337, 70); |
||
| 106 |
snapLastCall("ERC6909Claims transferFrom with approval");
|
||
| 107 | |||
| 108 |
assertEq(token.allowance(sender, address(this), 1337), 30); |
||
| 109 |
assertEq(token.balanceOf(sender, 1337), 30); |
||
| 110 |
assertEq(token.balanceOf(receiver, 1337), 70); |
||
| 111 |
} |
||
| 112 | |||
| 113 |
function testTransferFromWithInfiniteApproval() public {
|
||
| 114 |
address sender = address(0xABCD); |
||
| 115 |
address receiver = address(0xBEEF); |
||
| 116 | |||
| 117 |
token.mint(sender, 1337, 100); |
||
| 118 | |||
| 119 |
vm.prank(sender); |
||
| 120 |
token.approve(address(this), 1337, type(uint256).max); |
||
| 121 | |||
| 122 |
token.transferFrom(sender, receiver, 1337, 70); |
||
| 123 |
snapLastCall("ERC6909Claims transferFrom with infinite approval");
|
||
| 124 | |||
| 125 |
assertEq(token.allowance(sender, address(this), 1337), type(uint256).max); |
||
| 126 |
assertEq(token.balanceOf(sender, 1337), 30); |
||
| 127 |
assertEq(token.balanceOf(receiver, 1337), 70); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
function testTransferFromAsOperator() public {
|
||
| 131 |
address sender = address(0xABCD); |
||
| 132 |
address receiver = address(0xBEEF); |
||
| 133 | |||
| 134 |
token.mint(sender, 1337, 100); |
||
| 135 | |||
| 136 |
vm.prank(sender); |
||
| 137 |
token.setOperator(address(this), true); |
||
| 138 | |||
| 139 |
token.transferFrom(sender, receiver, 1337, 70); |
||
| 140 |
snapLastCall("ERC6909Claims transferFrom as operator");
|
||
| 141 | |||
| 142 |
assertEq(token.balanceOf(sender, 1337), 30); |
||
| 143 |
assertEq(token.balanceOf(receiver, 1337), 70); |
||
| 144 |
} |
||
| 145 | |||
| 146 |
function testFailMintBalanceOverflow() public {
|
||
| 147 |
token.mint(address(0xDEAD), 1337, type(uint256).max); |
||
| 148 |
token.mint(address(0xDEAD), 1337, 1); |
||
| 149 |
} |
||
| 150 | |||
| 151 |
function testFailTransferBalanceUnderflow() public {
|
||
| 152 |
address sender = address(0xABCD); |
||
| 153 |
address receiver = address(0xBEEF); |
||
| 154 | |||
| 155 |
vm.prank(sender); |
||
| 156 |
token.transferFrom(sender, receiver, 1337, 1); |
||
| 157 |
} |
||
| 158 | |||
| 159 |
function testFailTransferBalanceOverflow() public {
|
||
| 160 |
address sender = address(0xABCD); |
||
| 161 |
address receiver = address(0xBEEF); |
||
| 162 | |||
| 163 |
token.mint(sender, 1337, type(uint256).max); |
||
| 164 | |||
| 165 |
vm.prank(sender); |
||
| 166 |
token.transferFrom(sender, receiver, 1337, type(uint256).max); |
||
| 167 | |||
| 168 |
token.mint(sender, 1337, 1); |
||
| 169 | |||
| 170 |
vm.prank(sender); |
||
| 171 |
token.transferFrom(sender, receiver, 1337, 1); |
||
| 172 |
} |
||
| 173 | |||
| 174 |
function testFailTransferFromBalanceUnderflow() public {
|
||
| 175 |
address sender = address(0xABCD); |
||
| 176 |
address receiver = address(0xBEEF); |
||
| 177 | |||
| 178 |
vm.prank(sender); |
||
| 179 |
token.transferFrom(sender, receiver, 1337, 1); |
||
| 180 |
} |
||
| 181 | |||
| 182 |
function testFailTransferFromBalanceOverflow() public {
|
||
| 183 |
address sender = address(0xABCD); |
||
| 184 |
address receiver = address(0xBEEF); |
||
| 185 | |||
| 186 |
token.mint(sender, 1337, type(uint256).max); |
||
| 187 | |||
| 188 |
vm.prank(sender); |
||
| 189 |
token.transferFrom(sender, receiver, 1337, type(uint256).max); |
||
| 190 | |||
| 191 |
token.mint(sender, 1337, 1); |
||
| 192 | |||
| 193 |
vm.prank(sender); |
||
| 194 |
token.transferFrom(sender, receiver, 1337, 1); |
||
| 195 |
} |
||
| 196 | |||
| 197 |
function testFailTransferFromNotAuthorized() public {
|
||
| 198 |
address sender = address(0xABCD); |
||
| 199 |
address receiver = address(0xBEEF); |
||
| 200 | |||
| 201 |
token.mint(sender, 1337, 100); |
||
| 202 | |||
| 203 |
token.transferFrom(sender, receiver, 1337, 100); |
||
| 204 |
} |
||
| 205 | |||
| 206 |
function testMint(address receiver, uint256 id, uint256 amount) public {
|
||
| 207 |
token.mint(receiver, id, amount); |
||
| 208 | |||
| 209 |
assertEq(token.balanceOf(receiver, id), amount); |
||
| 210 |
} |
||
| 211 | |||
| 212 |
function testBurn(address sender, uint256 id, uint256 amount) public {
|
||
| 213 |
token.mint(sender, id, amount); |
||
| 214 |
vm.prank(sender); |
||
| 215 |
token.burn(id, amount); |
||
| 216 | |||
| 217 |
assertEq(token.balanceOf(sender, id), 0); |
||
| 218 |
} |
||
| 219 | |||
| 220 |
function testSetOperator(address operator, bool approved) public {
|
||
| 221 |
token.setOperator(operator, approved); |
||
| 222 | |||
| 223 |
assertEq(token.isOperator(address(this), operator), approved); |
||
| 224 |
} |
||
| 225 | |||
| 226 |
function testApprove(address spender, uint256 id, uint256 amount) public {
|
||
| 227 |
token.approve(spender, id, amount); |
||
| 228 | |||
| 229 |
assertEq(token.allowance(address(this), spender, id), amount); |
||
| 230 |
} |
||
| 231 | |||
| 232 |
function testTransfer(address sender, address receiver, uint256 id, uint256 mintAmount, uint256 transferAmount) |
||
| 233 |
public |
||
| 234 |
{
|
||
| 235 |
transferAmount = bound(transferAmount, 0, mintAmount); |
||
| 236 | |||
| 237 |
token.mint(sender, id, mintAmount); |
||
| 238 | |||
| 239 |
vm.prank(sender); |
||
| 240 |
token.transfer(receiver, id, transferAmount); |
||
| 241 | |||
| 242 |
if (sender == receiver) {
|
||
| 243 |
assertEq(token.balanceOf(sender, id), mintAmount); |
||
| 244 |
} else {
|
||
| 245 |
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount); |
||
| 246 |
assertEq(token.balanceOf(receiver, id), transferAmount); |
||
| 247 |
} |
||
| 248 |
} |
||
| 249 | |||
| 250 |
function testTransferFromWithApproval( |
||
| 251 |
address sender, |
||
| 252 |
address receiver, |
||
| 253 |
uint256 id, |
||
| 254 |
uint256 mintAmount, |
||
| 255 |
uint256 transferAmount |
||
| 256 |
) public {
|
||
| 257 |
transferAmount = bound(transferAmount, 0, mintAmount); |
||
| 258 | |||
| 259 |
token.mint(sender, id, mintAmount); |
||
| 260 | |||
| 261 |
vm.prank(sender); |
||
| 262 |
token.approve(address(this), id, mintAmount); |
||
| 263 | |||
| 264 |
token.transferFrom(sender, receiver, id, transferAmount); |
||
| 265 | |||
| 266 |
if (mintAmount == type(uint256).max) {
|
||
| 267 |
assertEq(token.allowance(sender, address(this), id), type(uint256).max); |
||
| 268 |
} else {
|
||
| 269 |
if (sender != address(this)) {
|
||
| 270 |
assertEq(token.allowance(sender, address(this), id), mintAmount - transferAmount); |
||
| 271 |
} else {
|
||
| 272 |
assertEq(token.allowance(sender, address(this), id), mintAmount); |
||
| 273 |
} |
||
| 274 |
} |
||
| 275 | |||
| 276 |
if (sender == receiver) {
|
||
| 277 |
assertEq(token.balanceOf(sender, id), mintAmount); |
||
| 278 |
} else {
|
||
| 279 |
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount); |
||
| 280 |
assertEq(token.balanceOf(receiver, id), transferAmount); |
||
| 281 |
} |
||
| 282 |
} |
||
| 283 | |||
| 284 |
function testTransferFromWithInfiniteApproval( |
||
| 285 |
address sender, |
||
| 286 |
address receiver, |
||
| 287 |
uint256 id, |
||
| 288 |
uint256 mintAmount, |
||
| 289 |
uint256 transferAmount |
||
| 290 |
) public {
|
||
| 291 |
transferAmount = bound(transferAmount, 0, mintAmount); |
||
| 292 | |||
| 293 |
token.mint(sender, id, mintAmount); |
||
| 294 | |||
| 295 |
vm.prank(sender); |
||
| 296 |
token.approve(address(this), id, type(uint256).max); |
||
| 297 | |||
| 298 |
token.transferFrom(sender, receiver, id, transferAmount); |
||
| 299 | |||
| 300 |
assertEq(token.allowance(sender, address(this), id), type(uint256).max); |
||
| 301 | |||
| 302 |
if (sender == receiver) {
|
||
| 303 |
assertEq(token.balanceOf(sender, id), mintAmount); |
||
| 304 |
} else {
|
||
| 305 |
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount); |
||
| 306 |
assertEq(token.balanceOf(receiver, id), transferAmount); |
||
| 307 |
} |
||
| 308 |
} |
||
| 309 | |||
| 310 |
function testTransferFromAsOperator( |
||
| 311 |
address sender, |
||
| 312 |
address receiver, |
||
| 313 |
uint256 id, |
||
| 314 |
uint256 mintAmount, |
||
| 315 |
uint256 transferAmount |
||
| 316 |
) public {
|
||
| 317 |
transferAmount = bound(transferAmount, 0, mintAmount); |
||
| 318 | |||
| 319 |
token.mint(sender, id, mintAmount); |
||
| 320 | |||
| 321 |
vm.prank(sender); |
||
| 322 |
token.setOperator(address(this), true); |
||
| 323 | |||
| 324 |
token.transferFrom(sender, receiver, id, transferAmount); |
||
| 325 | |||
| 326 |
if (sender == receiver) {
|
||
| 327 |
assertEq(token.balanceOf(sender, id), mintAmount); |
||
| 328 |
} else {
|
||
| 329 |
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount); |
||
| 330 |
assertEq(token.balanceOf(receiver, id), transferAmount); |
||
| 331 |
} |
||
| 332 |
} |
||
| 333 | |||
| 334 |
function testFailTransferBalanceUnderflow(address sender, address receiver, uint256 id, uint256 amount) public {
|
||
| 335 |
amount = bound(amount, 1, type(uint256).max); |
||
| 336 | |||
| 337 |
vm.prank(sender); |
||
| 338 |
token.transfer(receiver, id, amount); |
||
| 339 |
} |
||
| 340 | |||
| 341 |
function testFailTransferBalanceOverflow(address sender, address receiver, uint256 id, uint256 amount) public {
|
||
| 342 |
amount = bound(amount, 1, type(uint256).max); |
||
| 343 |
uint256 overflowAmount = type(uint256).max - amount + 1; |
||
| 344 | |||
| 345 |
token.mint(sender, id, amount); |
||
| 346 | |||
| 347 |
vm.prank(sender); |
||
| 348 |
token.transfer(receiver, id, amount); |
||
| 349 | |||
| 350 |
token.mint(sender, id, overflowAmount); |
||
| 351 | |||
| 352 |
vm.prank(sender); |
||
| 353 |
token.transfer(receiver, id, overflowAmount); |
||
| 354 |
} |
||
| 355 | |||
| 356 |
function testFailTransferFromBalanceUnderflow(address sender, address receiver, uint256 id, uint256 amount) |
||
| 357 |
public |
||
| 358 |
{
|
||
| 359 |
amount = bound(amount, 1, type(uint256).max); |
||
| 360 | |||
| 361 |
vm.prank(sender); |
||
| 362 |
token.transferFrom(sender, receiver, id, amount); |
||
| 363 |
} |
||
| 364 | |||
| 365 |
function testFailTransferFromBalanceOverflow(address sender, address receiver, uint256 id, uint256 amount) public {
|
||
| 366 |
amount = bound(amount, 1, type(uint256).max); |
||
| 367 |
uint256 overflowAmount = type(uint256).max - amount + 1; |
||
| 368 | |||
| 369 |
token.mint(sender, id, amount); |
||
| 370 | |||
| 371 |
vm.prank(sender); |
||
| 372 |
token.transferFrom(sender, receiver, id, amount); |
||
| 373 | |||
| 374 |
token.mint(sender, id, overflowAmount); |
||
| 375 | |||
| 376 |
vm.prank(sender); |
||
| 377 |
token.transferFrom(sender, receiver, id, overflowAmount); |
||
| 378 |
} |
||
| 379 | |||
| 380 |
function testFailTransferFromNotAuthorized(address sender, address receiver, uint256 id, uint256 amount) public {
|
||
| 381 |
amount = bound(amount, 1, type(uint256).max); |
||
| 382 | |||
| 383 |
token.mint(sender, id, amount); |
||
| 384 | |||
| 385 |
vm.assume(sender != address(this)); |
||
| 386 |
token.transferFrom(sender, receiver, id, amount); |
||
| 387 |
} |
||
| 388 |
} |
||
| 389 |
| Lines covered: | 0 / 34 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Extsload} from "../src/Extsload.sol";
|
||
| 6 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 7 | |||
| 8 |
contract Loadable is Extsload {}
|
||
| 9 | |||
| 10 |
/// @author philogy <https://github.com/philogy> |
||
| 11 |
contract ExtsloadTest is Test, GasSnapshot {
|
||
| 12 |
Loadable loadable = new Loadable(); |
||
| 13 | |||
| 14 |
function test_load10_sparse() public {
|
||
| 15 |
bytes32[] memory keys = new bytes32[](10); |
||
| 16 |
for (uint256 i = 0; i < keys.length; i++) {
|
||
| 17 |
keys[i] = keccak256(abi.encode(i)); |
||
| 18 |
vm.store(address(loadable), keys[i], bytes32(i)); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
bytes32[] memory values = loadable.extsload(keys); |
||
| 22 |
snapLastCall("sparse external sload");
|
||
| 23 |
assertEq(values.length, keys.length); |
||
| 24 |
for (uint256 i = 0; i < values.length; i++) {
|
||
| 25 |
assertEq(values[i], bytes32(i)); |
||
| 26 |
} |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function test_fuzz_consecutiveExtsload(uint256 startSlot, uint256 length, uint256 seed) public {
|
||
| 30 |
length = bound(length, 0, 1000); |
||
| 31 |
startSlot = bound(startSlot, 0, type(uint256).max - length); |
||
| 32 |
for (uint256 i; i < length; ++i) {
|
||
| 33 |
vm.store(address(loadable), bytes32(startSlot + i), keccak256(abi.encode(i, seed))); |
||
| 34 |
} |
||
| 35 |
bytes32[] memory values = loadable.extsload(bytes32(startSlot), length); |
||
| 36 |
assertEq(values.length, length); |
||
| 37 |
for (uint256 i; i < length; ++i) {
|
||
| 38 |
assertEq(values[i], keccak256(abi.encode(i, seed))); |
||
| 39 |
} |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function test_fuzz_extsload(uint256 length, uint256 seed, bytes memory dirtyBits) public {
|
||
| 43 |
length = bound(length, 0, 1000); |
||
| 44 |
bytes32[] memory slots = new bytes32[](length); |
||
| 45 |
bytes32[] memory expected = new bytes32[](length); |
||
| 46 |
for (uint256 i; i < length; ++i) {
|
||
| 47 |
slots[i] = keccak256(abi.encode(i, seed)); |
||
| 48 |
expected[i] = keccak256(abi.encode(slots[i])); |
||
| 49 |
vm.store(address(loadable), slots[i], expected[i]); |
||
| 50 |
} |
||
| 51 |
bytes32[] memory values = loadable.extsload(slots); |
||
| 52 |
assertEq(values, expected); |
||
| 53 |
// test with dirty bits |
||
| 54 |
bytes memory data = abi.encodeWithSignature("extsload(bytes32[])", (slots));
|
||
| 55 |
bytes memory malformedData = bytes.concat(data, dirtyBits); |
||
| 56 |
(bool success, bytes memory returnData) = address(loadable).staticcall(malformedData); |
||
| 57 |
assertTrue(success, "extsload failed"); |
||
| 58 |
assertEq(returnData.length % 0x20, 0, "return data length is not a multiple of 32"); |
||
| 59 |
assertEq(abi.decode(returnData, (bytes32[])), expected); |
||
| 60 |
} |
||
| 61 |
} |
||
| 62 |
| Lines covered: | 0 / 132 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 6 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 9 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 10 |
import {Position} from "src/libraries/Position.sol";
|
||
| 11 |
import {PoolId} from "src/types/PoolId.sol";
|
||
| 12 |
import {PoolModifyLiquidityTest} from "../src/test/PoolModifyLiquidityTest.sol";
|
||
| 13 |
import {Constants} from "./utils/Constants.sol";
|
||
| 14 |
import {Currency} from "src/types/Currency.sol";
|
||
| 15 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 16 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 17 |
import {JavascriptFfi} from "./utils/JavascriptFfi.sol";
|
||
| 18 |
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
|
||
| 19 |
import {Fuzzers} from "../src/test/Fuzzers.sol";
|
||
| 20 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 21 |
import {toBalanceDelta} from "src/types/BalanceDelta.sol";
|
||
| 22 |
import {Logger} from "./utils/Logger.sol";
|
||
| 23 | |||
| 24 |
contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers, GasSnapshot {
|
||
| 25 |
using StateLibrary for IPoolManager; |
||
| 26 | |||
| 27 |
PoolKey simpleKey; // vanilla pool key |
||
| 28 |
PoolId simplePoolId; // id for vanilla pool key |
||
| 29 | |||
| 30 |
bytes32 SALT = hex"CAFF"; |
||
| 31 | |||
| 32 |
int128 constant ONE_PIP = 1e6; |
||
| 33 | |||
| 34 |
IPoolManager.ModifyLiquidityParams public LIQ_PARAM_NO_SALT = |
||
| 35 |
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
|
||
| 36 | |||
| 37 |
IPoolManager.ModifyLiquidityParams public LIQ_PARAM_SALT = |
||
| 38 |
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: SALT});
|
||
| 39 | |||
| 40 |
function setUp() public {
|
||
| 41 |
deployFreshManagerAndRouters(); |
||
| 42 |
deployMintAndApprove2Currencies(); |
||
| 43 |
(simpleKey, simplePoolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
/*////////////////////////////////////////////////////////////// |
||
| 47 |
Fuzz Add Liquidity |
||
| 48 |
//////////////////////////////////////////////////////////////*/ |
||
| 49 | |||
| 50 |
/// forge-config: default.fuzz.runs = 10 |
||
| 51 |
/// forge-config: pr.fuzz.runs = 10 |
||
| 52 |
/// forge-config: ci.fuzz.runs = 500 |
||
| 53 |
function test_ffi_fuzz_addLiquidity_defaultPool_ReturnsCorrectLiquidityDelta( |
||
| 54 |
IPoolManager.ModifyLiquidityParams memory paramSeed |
||
| 55 |
) public {
|
||
| 56 |
// Sanitize the fuzzed params to get valid tickLower, tickUpper, and liquidityDelta. |
||
| 57 |
// We use SQRT_PRICE_1_1 because the simpleKey pool has initial sqrtPrice of SQRT_PRICE_1_1. |
||
| 58 |
IPoolManager.ModifyLiquidityParams memory params = |
||
| 59 |
createFuzzyLiquidityParams(simpleKey, paramSeed, SQRT_PRICE_1_1); |
||
| 60 | |||
| 61 |
logParams(params); |
||
| 62 | |||
| 63 |
(BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(simpleKey, params, ZERO_BYTES); |
||
| 64 | |||
| 65 |
(int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(simplePoolId, params); |
||
| 66 | |||
| 67 |
_checkError(delta.amount0(), jsDelta0, "amount0 is off by more than one pip"); |
||
| 68 |
_checkError(delta.amount1(), jsDelta1, "amount1 is off by more than one pip"); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
// Static edge case, no fuzz test, to make sure we test max tickspacing. |
||
| 72 |
function test_ffi_addLiqudity_weirdPool_0_returnsCorrectLiquidityDelta() public {
|
||
| 73 |
// Use a pool with TickSpacing of MAX_TICK_SPACING |
||
| 74 |
(PoolKey memory wp0, PoolId wpId0) = initPool( |
||
| 75 |
currency0, currency1, IHooks(address(0)), 500, TickMath.MAX_TICK_SPACING, SQRT_PRICE_1_1, ZERO_BYTES |
||
| 76 |
); |
||
| 77 | |||
| 78 |
// Set the params to add random amount of liquidity to random tick boundary. |
||
| 79 |
int24 tickUpper = TickMath.MAX_TICK_SPACING * 4; |
||
| 80 |
int24 tickLower = TickMath.MAX_TICK_SPACING * -9; |
||
| 81 |
IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({
|
||
| 82 |
tickLower: tickLower, |
||
| 83 |
tickUpper: tickUpper, |
||
| 84 |
liquidityDelta: 16787899214600939458, |
||
| 85 |
salt: 0 |
||
| 86 |
}); |
||
| 87 | |||
| 88 |
(BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES); |
||
| 89 | |||
| 90 |
(int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(wpId0, params); |
||
| 91 | |||
| 92 |
_checkError(delta.amount0(), jsDelta0, "amount0 is off by more than one pip"); |
||
| 93 |
_checkError(delta.amount1(), jsDelta1, "amount1 is off by more than one pip"); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
// Static edge case, no fuzz test, to make sure we test min tick spacing. |
||
| 97 |
function test_ffi_addLiqudity_weirdPool_1_returnsCorrectLiquidityDelta() public {
|
||
| 98 |
// Use a pool with TickSpacing of MIN_TICK_SPACING |
||
| 99 |
(PoolKey memory wp0, PoolId wpId0) = initPool( |
||
| 100 |
currency0, currency1, IHooks(address(0)), 551, TickMath.MIN_TICK_SPACING, SQRT_PRICE_1_1, ZERO_BYTES |
||
| 101 |
); |
||
| 102 | |||
| 103 |
// Set the params to add random amount of liquidity to random tick boundary. |
||
| 104 |
int24 tickUpper = TickMath.MIN_TICK_SPACING * 17; |
||
| 105 |
int24 tickLower = TickMath.MIN_TICK_SPACING * 9; |
||
| 106 |
IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({
|
||
| 107 |
tickLower: tickLower, |
||
| 108 |
tickUpper: tickUpper, |
||
| 109 |
liquidityDelta: 922871614499955267459963, |
||
| 110 |
salt: 0 |
||
| 111 |
}); |
||
| 112 | |||
| 113 |
params.tickLower = 10; |
||
| 114 | |||
| 115 |
(BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES); |
||
| 116 | |||
| 117 |
(int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(wpId0, params); |
||
| 118 | |||
| 119 |
_checkError(delta.amount0(), jsDelta0, "amount0 is off by more than one pip"); |
||
| 120 |
_checkError(delta.amount1(), jsDelta1, "amount1 is off by more than one pip"); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function _modifyLiquidityJS(PoolId poolId, IPoolManager.ModifyLiquidityParams memory params) |
||
| 124 |
public |
||
| 125 |
returns (int128, int128) |
||
| 126 |
{
|
||
| 127 |
(uint256 price, int24 tick,,) = manager.getSlot0(poolId); |
||
| 128 | |||
| 129 |
string memory jsParameters = string( |
||
| 130 |
abi.encodePacked( |
||
| 131 |
vm.toString(params.tickLower), |
||
| 132 |
",", |
||
| 133 |
vm.toString(params.tickUpper), |
||
| 134 |
",", |
||
| 135 |
vm.toString(params.liquidityDelta), |
||
| 136 |
",", |
||
| 137 |
vm.toString(tick), |
||
| 138 |
",", |
||
| 139 |
vm.toString(price) |
||
| 140 |
) |
||
| 141 |
); |
||
| 142 | |||
| 143 |
string memory scriptName = "forge-test-getModifyLiquidityResult"; |
||
| 144 |
bytes memory jsResult = runScript(scriptName, jsParameters); |
||
| 145 | |||
| 146 |
int128[] memory result = abi.decode(jsResult, (int128[])); |
||
| 147 |
int128 jsDelta0 = result[0]; |
||
| 148 |
int128 jsDelta1 = result[1]; |
||
| 149 |
return (jsDelta0, jsDelta1); |
||
| 150 |
} |
||
| 151 | |||
| 152 |
// assert solc/js result is at most off by 1/100th of a bip (aka one pip) |
||
| 153 |
function _checkError(int128 solc, int128 js, string memory errMsg) public pure {
|
||
| 154 |
if (solc != js) {
|
||
| 155 |
// Ensures no div by 0 in the case of one-sided liquidity adds. |
||
| 156 |
(int128 gtResult, int128 ltResult) = js > solc ? (js, solc) : (solc, js); |
||
| 157 |
int128 resultsDiff = gtResult - ltResult; |
||
| 158 |
assertEq(resultsDiff * ONE_PIP / js, 0, errMsg); |
||
| 159 |
} |
||
| 160 |
} |
||
| 161 | |||
| 162 |
/*////////////////////////////////////////////////////////////// |
||
| 163 |
Salt |
||
| 164 |
//////////////////////////////////////////////////////////////*/ |
||
| 165 | |||
| 166 |
function test_modifyLiquidity_samePosition_zeroSalt_isUpdated() public {
|
||
| 167 |
Position.Info memory position = manager.getPosition( |
||
| 168 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 169 |
); |
||
| 170 |
assertEq(position.liquidity, 0); |
||
| 171 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_NO_SALT, ZERO_BYTES); |
||
| 172 |
position = manager.getPosition( |
||
| 173 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 174 |
); |
||
| 175 | |||
| 176 |
assertEq(position.liquidity, uint128(uint256(LIQ_PARAM_NO_SALT.liquidityDelta))); |
||
| 177 | |||
| 178 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_NO_SALT, ZERO_BYTES); |
||
| 179 |
Position.Info memory updated = manager.getPosition( |
||
| 180 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 181 |
); |
||
| 182 |
assertEq(updated.liquidity, position.liquidity + uint128(uint256(LIQ_PARAM_NO_SALT.liquidityDelta))); |
||
| 183 |
} |
||
| 184 | |||
| 185 |
function test_modifyLiquidity_samePosition_withSalt_isUpdated() public {
|
||
| 186 |
Position.Info memory position = manager.getPosition( |
||
| 187 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 188 |
); |
||
| 189 |
assertEq(position.liquidity, 0); |
||
| 190 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 191 |
position = manager.getPosition( |
||
| 192 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 193 |
); |
||
| 194 |
assertEq(position.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); |
||
| 195 | |||
| 196 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 197 |
Position.Info memory updated = manager.getPosition( |
||
| 198 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 199 |
); |
||
| 200 |
assertEq(updated.liquidity, position.liquidity + uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); |
||
| 201 |
} |
||
| 202 | |||
| 203 |
function test_modifyLiquidity_sameTicks_withDifferentSalt_isNotUpdated() public {
|
||
| 204 |
Position.Info memory positionNoSalt = manager.getPosition( |
||
| 205 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 206 |
); |
||
| 207 | |||
| 208 |
Position.Info memory positionSalt = manager.getPosition( |
||
| 209 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 210 |
); |
||
| 211 |
assertEq(positionNoSalt.liquidity, 0); |
||
| 212 |
assertEq(positionSalt.liquidity, 0); |
||
| 213 | |||
| 214 |
// Modify the liquidity with the salt. |
||
| 215 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 216 | |||
| 217 |
positionNoSalt = manager.getPosition( |
||
| 218 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 219 |
); |
||
| 220 | |||
| 221 |
positionSalt = manager.getPosition( |
||
| 222 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 223 |
); |
||
| 224 | |||
| 225 |
assertEq(positionNoSalt.liquidity, 0); // This position does not have liquidity. |
||
| 226 |
assertEq(positionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); // This position does. |
||
| 227 | |||
| 228 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_NO_SALT, ZERO_BYTES); // Now the positions should have the same liquidity. |
||
| 229 | |||
| 230 |
positionNoSalt = manager.getPosition( |
||
| 231 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 232 |
); |
||
| 233 | |||
| 234 |
positionSalt = manager.getPosition( |
||
| 235 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 236 |
); |
||
| 237 | |||
| 238 |
// positionSalt should still only have the original liquidity deposited to it |
||
| 239 |
assertEq(positionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); |
||
| 240 |
assertEq(positionNoSalt.liquidity, positionSalt.liquidity); |
||
| 241 | |||
| 242 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 243 |
Position.Info memory updatedWithSalt = manager.getPosition( |
||
| 244 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 245 |
); |
||
| 246 |
Position.Info memory updatedNoSalt = manager.getPosition( |
||
| 247 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0 |
||
| 248 |
); |
||
| 249 | |||
| 250 |
assertEq(updatedWithSalt.liquidity, positionSalt.liquidity + uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); |
||
| 251 |
assertGt(updatedWithSalt.liquidity, updatedNoSalt.liquidity); |
||
| 252 |
assertEq(updatedNoSalt.liquidity, positionNoSalt.liquidity); |
||
| 253 |
} |
||
| 254 | |||
| 255 |
function test_modifyLiquidity_sameSalt_differentLiquidityRouters_doNotEditSamePosition() public {
|
||
| 256 |
// Set up new router. |
||
| 257 |
PoolModifyLiquidityTest modifyLiquidityRouter2 = new PoolModifyLiquidityTest(manager); |
||
| 258 | |||
| 259 |
MockERC20(Currency.unwrap(currency0)).approve(address(modifyLiquidityRouter2), Constants.MAX_UINT256); |
||
| 260 |
MockERC20(Currency.unwrap(currency1)).approve(address(modifyLiquidityRouter2), Constants.MAX_UINT256); |
||
| 261 | |||
| 262 |
IPoolManager.ModifyLiquidityParams memory LIQ_PARAM_SALT_2 = |
||
| 263 |
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 2e18, salt: SALT});
|
||
| 264 | |||
| 265 |
// Get the uninitialized positions and assert they have no liquidity. |
||
| 266 |
Position.Info memory positionSalt = manager.getPosition( |
||
| 267 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 268 |
); |
||
| 269 | |||
| 270 |
Position.Info memory positionSalt2 = manager.getPosition( |
||
| 271 |
simplePoolId, address(modifyLiquidityRouter2), LIQ_PARAM_SALT_2.tickLower, LIQ_PARAM_SALT_2.tickUpper, SALT |
||
| 272 |
); |
||
| 273 | |||
| 274 |
assertEq(positionSalt.liquidity, 0); |
||
| 275 |
assertEq(positionSalt2.liquidity, 0); |
||
| 276 | |||
| 277 |
// Modify the liquidity with the salt with the first router. |
||
| 278 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 279 | |||
| 280 |
Position.Info memory updatedPositionSalt = manager.getPosition( |
||
| 281 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 282 |
); |
||
| 283 | |||
| 284 |
Position.Info memory updatedPositionSalt2 = manager.getPosition( |
||
| 285 |
simplePoolId, address(modifyLiquidityRouter2), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 286 |
); |
||
| 287 | |||
| 288 |
// Assert only the liquidity from the first router is updated. |
||
| 289 |
assertEq(updatedPositionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); |
||
| 290 |
assertEq(updatedPositionSalt2.liquidity, 0); |
||
| 291 | |||
| 292 |
// Modify the liquidity with the second router. |
||
| 293 |
modifyLiquidityRouter2.modifyLiquidity(simpleKey, LIQ_PARAM_SALT_2, ZERO_BYTES); |
||
| 294 | |||
| 295 |
updatedPositionSalt2 = manager.getPosition( |
||
| 296 |
simplePoolId, address(modifyLiquidityRouter2), LIQ_PARAM_SALT_2.tickLower, LIQ_PARAM_SALT_2.tickUpper, SALT |
||
| 297 |
); |
||
| 298 |
updatedPositionSalt = manager.getPosition( |
||
| 299 |
simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT |
||
| 300 |
); |
||
| 301 | |||
| 302 |
// Assert only the liquidity from the second router is updated. |
||
| 303 |
assertEq(updatedPositionSalt2.liquidity, uint128(uint256(LIQ_PARAM_SALT_2.liquidityDelta))); |
||
| 304 |
assertEq(updatedPositionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); |
||
| 305 |
} |
||
| 306 | |||
| 307 |
function test_gas_modifyLiquidity_newPosition() public {
|
||
| 308 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 309 |
snapLastCall("create new liquidity to a position with salt");
|
||
| 310 |
} |
||
| 311 | |||
| 312 |
function test_gas_modifyLiquidity_updateSamePosition_withSalt() public {
|
||
| 313 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 314 |
modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES); |
||
| 315 |
snapLastCall("add liquidity to already existing position with salt");
|
||
| 316 |
} |
||
| 317 |
} |
||
| 318 |
| Lines covered: | 0 / 27 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 5 |
import {Test} from "forge-std/Test.sol";
|
||
| 6 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 7 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 8 |
import {ProxyPoolManager} from "../src/test/ProxyPoolManager.sol";
|
||
| 9 |
import {NoDelegateCallTest} from "../src/test/NoDelegateCallTest.sol";
|
||
| 10 |
import {PoolManager} from "../src/PoolManager.sol";
|
||
| 11 |
import {NoDelegateCall} from "../src/NoDelegateCall.sol";
|
||
| 12 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 13 | |||
| 14 |
contract TestDelegateCall is Test, Deployers, GasSnapshot {
|
||
| 15 |
// override to use ProxyPoolManager |
||
| 16 |
function deployFreshManager() internal virtual override {
|
||
| 17 |
IPoolManager delegateManager = new PoolManager(500000); |
||
| 18 |
manager = new ProxyPoolManager(address(delegateManager), 500000); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
NoDelegateCallTest noDelegateCallTest; |
||
| 22 | |||
| 23 |
function setUp() public {
|
||
| 24 |
deployFreshManagerAndRouters(); |
||
| 25 | |||
| 26 |
noDelegateCallTest = new NoDelegateCallTest(); |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function test_gas_noDelegateCall() public {
|
||
| 30 |
snap( |
||
| 31 |
"NoDelegateCall", |
||
| 32 |
noDelegateCallTest.getGasCostOfCannotBeDelegateCalled() |
||
| 33 |
- noDelegateCallTest.getGasCostOfCanBeDelegateCalled() |
||
| 34 |
); |
||
| 35 |
} |
||
| 36 | |||
| 37 |
function test_delegateCallNoModifier() public {
|
||
| 38 |
(bool success,) = |
||
| 39 |
address(noDelegateCallTest).delegatecall(abi.encode(noDelegateCallTest.canBeDelegateCalled.selector)); |
||
| 40 |
assertTrue(success); |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_delegateCallWithModifier_revertsWithDelegateCallNotAllowed() public {
|
||
| 44 |
vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector); |
||
| 45 |
(bool success,) = |
||
| 46 |
address(noDelegateCallTest).delegatecall(abi.encode(noDelegateCallTest.cannotBeDelegateCalled.selector)); |
||
| 47 |
// note vm.expectRevert inverts success, so a true result here means it reverted |
||
| 48 |
assertTrue(success); |
||
| 49 |
} |
||
| 50 | |||
| 51 |
function test_externalCallToPrivateMethodWithModifer_succeeds() public view {
|
||
| 52 |
noDelegateCallTest.callsIntoNoDelegateCallFunction(); |
||
| 53 |
} |
||
| 54 | |||
| 55 |
function test_delegateCallFromExternalToPrivateMethodWithModifier_revertsWithDelegateCallNotAllowed() public {
|
||
| 56 |
vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector); |
||
| 57 |
(bool success,) = address(noDelegateCallTest).delegatecall( |
||
| 58 |
abi.encode(noDelegateCallTest.callsIntoNoDelegateCallFunction.selector) |
||
| 59 |
); |
||
| 60 |
// note vm.expectRevert inverts success, so a true result here means it reverted |
||
| 61 |
assertTrue(success); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function test_modifyLiquidity_noDelegateCall() public {
|
||
| 65 |
vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector); |
||
| 66 |
modifyLiquidityRouter.modifyLiquidity(uninitializedKey, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 67 | |||
| 68 |
vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector); |
||
| 69 |
modifyLiquidityRouter.modifyLiquidity(uninitializedKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function test_swap_noDelegateCall() public {
|
||
| 73 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 74 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 75 | |||
| 76 |
vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector); |
||
| 77 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
function test_donate_noDelegateCall() public {
|
||
| 81 |
vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector); |
||
| 82 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 83 |
} |
||
| 84 |
} |
||
| 85 |
| Lines covered: | 0 / 108 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 6 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 7 |
import {Actions} from "../src/test/ActionsRouter.sol";
|
||
| 8 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 9 |
import {MockERC20} from "forge-std/mocks/MockERC20.sol";
|
||
| 10 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 11 | |||
| 12 |
contract ClearTest is Test, Deployers {
|
||
| 13 |
function setUp() public {
|
||
| 14 |
initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0))); |
||
| 15 |
seedMoreLiquidity(key, 10e18, 10e18); |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function test_clear_reverts_negativeDelta() external {
|
||
| 19 |
uint256 amount = 1e18; |
||
| 20 | |||
| 21 |
Actions[] memory actions = new Actions[](2); |
||
| 22 |
bytes[] memory params = new bytes[](2); |
||
| 23 | |||
| 24 |
// Apply a negative delta. |
||
| 25 |
actions[0] = Actions.TAKE; |
||
| 26 |
params[0] = abi.encode(currency0, address(this), amount); |
||
| 27 | |||
| 28 |
actions[1] = Actions.CLEAR; |
||
| 29 |
params[1] = abi.encode(currency0, amount, false, ""); |
||
| 30 | |||
| 31 |
vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector); |
||
| 32 |
actionsRouter.executeActions(actions, params); |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function test_clear_reverts_positiveDelta_inputGreaterThanDelta() external {
|
||
| 36 |
uint256 amount = 1e18; |
||
| 37 |
Actions[] memory actions = new Actions[](5); |
||
| 38 |
bytes[] memory params = new bytes[](5); |
||
| 39 | |||
| 40 |
// Apply a positive delta. |
||
| 41 |
actions[0] = Actions.SYNC; |
||
| 42 |
params[0] = abi.encode(currency0); |
||
| 43 | |||
| 44 |
actions[1] = Actions.TRANSFER_FROM; |
||
| 45 |
params[1] = abi.encode(currency0, address(this), address(manager), amount); |
||
| 46 | |||
| 47 |
actions[2] = Actions.SETTLE; |
||
| 48 |
params[2] = abi.encode(currency0); |
||
| 49 | |||
| 50 |
// Delta should be equal to the positive amount. |
||
| 51 |
actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 52 |
params[3] = abi.encode(currency0, address(actionsRouter), amount); |
||
| 53 | |||
| 54 |
// Clear for 1 greater than the delta. |
||
| 55 |
actions[4] = Actions.CLEAR; |
||
| 56 |
params[4] = abi.encode(currency0, amount + 1, false, ""); |
||
| 57 | |||
| 58 |
vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector); |
||
| 59 |
actionsRouter.executeActions(actions, params); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function test_clear_reverts_positiveDelta_inputLessThanDelta() external {
|
||
| 63 |
uint256 amount = 1e18; |
||
| 64 |
Actions[] memory actions = new Actions[](5); |
||
| 65 |
bytes[] memory params = new bytes[](5); |
||
| 66 | |||
| 67 |
// Apply a positive delta. |
||
| 68 |
actions[0] = Actions.SYNC; |
||
| 69 |
params[0] = abi.encode(currency0); |
||
| 70 | |||
| 71 |
actions[1] = Actions.TRANSFER_FROM; |
||
| 72 |
params[1] = abi.encode(currency0, address(this), address(manager), amount); |
||
| 73 | |||
| 74 |
actions[2] = Actions.SETTLE; |
||
| 75 |
params[2] = abi.encode(currency0); |
||
| 76 | |||
| 77 |
actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 78 |
params[3] = abi.encode(currency0, address(actionsRouter), amount); |
||
| 79 | |||
| 80 |
// Clear for 1 less than the delta. |
||
| 81 |
actions[4] = Actions.CLEAR; |
||
| 82 |
params[4] = abi.encode(currency0, amount - 1, false, ""); |
||
| 83 | |||
| 84 |
vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector); |
||
| 85 |
actionsRouter.executeActions(actions, params); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function test_clear_reverts_positiveDelta_inputZero() external {
|
||
| 89 |
uint256 amount = 1e18; |
||
| 90 |
Actions[] memory actions = new Actions[](5); |
||
| 91 |
bytes[] memory params = new bytes[](5); |
||
| 92 | |||
| 93 |
// Apply a positive delta. |
||
| 94 |
actions[0] = Actions.SYNC; |
||
| 95 |
params[0] = abi.encode(currency0); |
||
| 96 | |||
| 97 |
actions[1] = Actions.TRANSFER_FROM; |
||
| 98 |
params[1] = abi.encode(currency0, address(this), address(manager), amount); |
||
| 99 | |||
| 100 |
actions[2] = Actions.SETTLE; |
||
| 101 |
params[2] = abi.encode(currency0); |
||
| 102 | |||
| 103 |
actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 104 |
params[3] = abi.encode(currency0, address(actionsRouter), amount); |
||
| 105 | |||
| 106 |
// Clear with 0. |
||
| 107 |
actions[4] = Actions.CLEAR; |
||
| 108 |
params[4] = abi.encode(currency0, 0, false, ""); |
||
| 109 | |||
| 110 |
vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector); |
||
| 111 |
actionsRouter.executeActions(actions, params); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function test_clear_zeroDelta_inputZero_isUnchanged() external {
|
||
| 115 |
Actions[] memory actions = new Actions[](5); |
||
| 116 |
bytes[] memory params = new bytes[](5); |
||
| 117 | |||
| 118 |
actions[0] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 119 |
params[0] = abi.encode(0); |
||
| 120 | |||
| 121 |
actions[1] = Actions.ASSERT_DELTA_EQUALS; |
||
| 122 |
params[1] = abi.encode(currency0, address(actionsRouter), 0); |
||
| 123 | |||
| 124 |
// Clear with 0. |
||
| 125 |
actions[2] = Actions.CLEAR; |
||
| 126 |
params[2] = abi.encode(currency0, 0, false, ""); |
||
| 127 | |||
| 128 |
actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 129 |
params[3] = abi.encode(currency0, address(actionsRouter), 0); |
||
| 130 | |||
| 131 |
actions[4] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 132 |
params[4] = abi.encode(0); |
||
| 133 | |||
| 134 |
actionsRouter.executeActions(actions, params); |
||
| 135 |
} |
||
| 136 | |||
| 137 |
function test_clear_reverts_zeroDelta_inputNonZero() external {
|
||
| 138 |
uint256 amount = 1e18; |
||
| 139 |
Actions[] memory actions = new Actions[](3); |
||
| 140 |
bytes[] memory params = new bytes[](3); |
||
| 141 | |||
| 142 |
actions[0] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 143 |
params[0] = abi.encode(0); |
||
| 144 | |||
| 145 |
actions[1] = Actions.ASSERT_DELTA_EQUALS; |
||
| 146 |
params[1] = abi.encode(currency0, address(actionsRouter), 0); |
||
| 147 | |||
| 148 |
// Clear with nonZero. |
||
| 149 |
actions[2] = Actions.CLEAR; |
||
| 150 |
params[2] = abi.encode(currency0, amount, false, ""); |
||
| 151 | |||
| 152 |
vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector); |
||
| 153 |
actionsRouter.executeActions(actions, params); |
||
| 154 |
} |
||
| 155 | |||
| 156 |
function test_clear_positiveDelta_inputExact_succeeds() external {
|
||
| 157 |
uint256 amount = 1e18; |
||
| 158 |
Actions[] memory actions = new Actions[](8); |
||
| 159 |
bytes[] memory params = new bytes[](8); |
||
| 160 | |||
| 161 |
// Apply a positive delta. |
||
| 162 |
actions[0] = Actions.SYNC; |
||
| 163 |
params[0] = abi.encode(currency0); |
||
| 164 | |||
| 165 |
actions[1] = Actions.TRANSFER_FROM; |
||
| 166 |
params[1] = abi.encode(currency0, address(this), address(manager), amount); |
||
| 167 | |||
| 168 |
actions[2] = Actions.SETTLE; |
||
| 169 |
params[2] = abi.encode(currency0); |
||
| 170 | |||
| 171 |
// Delta should be equal to the positive amount. |
||
| 172 |
actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 173 |
params[3] = abi.encode(currency0, address(actionsRouter), amount); |
||
| 174 | |||
| 175 |
// Assert nonzero delta count is 1. |
||
| 176 |
actions[4] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 177 |
params[4] = abi.encode(1); |
||
| 178 | |||
| 179 |
// Clear the exact delta amount. |
||
| 180 |
actions[5] = Actions.CLEAR; |
||
| 181 |
params[5] = abi.encode(currency0, amount, false, ""); |
||
| 182 | |||
| 183 |
actions[6] = Actions.ASSERT_DELTA_EQUALS; |
||
| 184 |
params[6] = abi.encode(currency0, address(actionsRouter), 0); |
||
| 185 | |||
| 186 |
actions[7] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 187 |
params[7] = abi.encode(0); |
||
| 188 | |||
| 189 |
actionsRouter.executeActions(actions, params); |
||
| 190 |
} |
||
| 191 | |||
| 192 |
function test_clear_gas() external {
|
||
| 193 |
uint256 amount = 1e18; |
||
| 194 |
Actions[] memory actions = new Actions[](8); |
||
| 195 |
bytes[] memory params = new bytes[](8); |
||
| 196 | |||
| 197 |
// Apply a positive delta. |
||
| 198 |
actions[0] = Actions.SYNC; |
||
| 199 |
params[0] = abi.encode(currency0); |
||
| 200 | |||
| 201 |
actions[1] = Actions.TRANSFER_FROM; |
||
| 202 |
params[1] = abi.encode(currency0, address(this), address(manager), amount); |
||
| 203 | |||
| 204 |
actions[2] = Actions.SETTLE; |
||
| 205 |
params[2] = abi.encode(currency0); |
||
| 206 | |||
| 207 |
// Delta should be equal to the positive amount. |
||
| 208 |
actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 209 |
params[3] = abi.encode(currency0, address(actionsRouter), amount); |
||
| 210 | |||
| 211 |
// Assert nonzero delta count is 1. |
||
| 212 |
actions[4] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 213 |
params[4] = abi.encode(1); |
||
| 214 | |||
| 215 |
// Clear the exact delta amount. |
||
| 216 |
actions[5] = Actions.CLEAR; |
||
| 217 |
params[5] = abi.encode(currency0, amount, true, "clear"); |
||
| 218 | |||
| 219 |
actions[6] = Actions.ASSERT_DELTA_EQUALS; |
||
| 220 |
params[6] = abi.encode(currency0, address(actionsRouter), 0); |
||
| 221 | |||
| 222 |
actions[7] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS; |
||
| 223 |
params[7] = abi.encode(0); |
||
| 224 | |||
| 225 |
actionsRouter.executeActions(actions, params); |
||
| 226 |
} |
||
| 227 |
} |
||
| 228 |
| Lines covered: | 0 / 78 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 |
import {V3Helper, IUniswapV3Pool, IUniswapV3MintCallback, IUniswapV3SwapCallback} from "./utils/V3Helper.sol";
|
||
| 6 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 7 |
import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
|
||
| 8 |
import {Fuzzers} from "../src/test/Fuzzers.sol";
|
||
| 9 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 10 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 11 |
import {BalanceDelta, BalanceDeltaLibrary, toBalanceDelta} from "../src/types/BalanceDelta.sol";
|
||
| 12 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 13 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 14 |
import {SqrtPriceMath} from "../src/libraries/SqrtPriceMath.sol";
|
||
| 15 |
import {TickMath} from "../src/libraries/TickMath.sol";
|
||
| 16 |
import {SafeCast} from "../src/libraries/SafeCast.sol";
|
||
| 17 |
import {LiquidityAmounts} from "./utils/LiquidityAmounts.sol";
|
||
| 18 | |||
| 19 |
abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallback, IUniswapV3SwapCallback {
|
||
| 20 |
using CurrencyLibrary for Currency; |
||
| 21 | |||
| 22 |
function setUp() public virtual override {
|
||
| 23 |
super.setUp(); |
||
| 24 |
deployFreshManagerAndRouters(); |
||
| 25 |
deployMintAndApprove2Currencies(); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function initPools(uint24 fee, int24 tickSpacing, int256 sqrtPriceX96seed) |
||
| 29 |
internal |
||
| 30 |
returns (IUniswapV3Pool v3Pool, PoolKey memory key_, uint160 sqrtPriceX96) |
||
| 31 |
{
|
||
| 32 |
fee = uint24(bound(fee, 0, 999999)); |
||
| 33 |
tickSpacing = int24(bound(tickSpacing, 1, 16383)); |
||
| 34 |
// v3 pools don't allow overwriting existing fees, 500, 3000, 10000 are set by default in the constructor |
||
| 35 |
if (fee == 500) tickSpacing = 10; |
||
| 36 |
else if (fee == 3000) tickSpacing = 60; |
||
| 37 |
else if (fee == 10000) tickSpacing = 200; |
||
| 38 |
else v3Factory.enableFeeAmount(fee, tickSpacing); |
||
| 39 | |||
| 40 |
sqrtPriceX96 = createRandomSqrtPriceX96(tickSpacing, sqrtPriceX96seed); |
||
| 41 | |||
| 42 |
v3Pool = IUniswapV3Pool(v3Factory.createPool(Currency.unwrap(currency0), Currency.unwrap(currency1), fee)); |
||
| 43 |
v3Pool.initialize(sqrtPriceX96); |
||
| 44 | |||
| 45 |
key_ = PoolKey(currency0, currency1, fee, tickSpacing, IHooks(address(0))); |
||
| 46 |
manager.initialize(key_, sqrtPriceX96, ""); |
||
| 47 |
} |
||
| 48 | |||
| 49 |
function addLiquidity( |
||
| 50 |
IUniswapV3Pool v3Pool, |
||
| 51 |
PoolKey memory key_, |
||
| 52 |
uint160 sqrtPriceX96, |
||
| 53 |
int24 lowerTickUnsanitized, |
||
| 54 |
int24 upperTickUnsanitized, |
||
| 55 |
int256 liquidityDeltaUnbound, |
||
| 56 |
bool tight |
||
| 57 |
) internal {
|
||
| 58 |
IPoolManager.ModifyLiquidityParams memory v4LiquidityParams = IPoolManager.ModifyLiquidityParams({
|
||
| 59 |
tickLower: lowerTickUnsanitized, |
||
| 60 |
tickUpper: upperTickUnsanitized, |
||
| 61 |
liquidityDelta: liquidityDeltaUnbound, |
||
| 62 |
salt: 0 |
||
| 63 |
}); |
||
| 64 | |||
| 65 |
v4LiquidityParams = tight |
||
| 66 |
? createFuzzyLiquidityParamsWithTightBound(key_, v4LiquidityParams, sqrtPriceX96, 20) |
||
| 67 |
: createFuzzyLiquidityParams(key_, v4LiquidityParams, sqrtPriceX96); |
||
| 68 | |||
| 69 |
v3Pool.mint( |
||
| 70 |
address(this), |
||
| 71 |
v4LiquidityParams.tickLower, |
||
| 72 |
v4LiquidityParams.tickUpper, |
||
| 73 |
uint128(int128(v4LiquidityParams.liquidityDelta)), |
||
| 74 |
"" |
||
| 75 |
); |
||
| 76 | |||
| 77 |
modifyLiquidityRouter.modifyLiquidity(key_, v4LiquidityParams, ""); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
function swap(IUniswapV3Pool pool, PoolKey memory key_, bool zeroForOne, int128 amountSpecified) |
||
| 81 |
internal |
||
| 82 |
returns (int256 amount0Diff, int256 amount1Diff) |
||
| 83 |
{
|
||
| 84 |
if (amountSpecified == 0) amountSpecified = 1; |
||
| 85 |
if (amountSpecified == type(int128).min) amountSpecified = type(int128).min + 1; |
||
| 86 |
// v3 swap |
||
| 87 |
(int256 amount0Delta, int256 amount1Delta) = pool.swap( |
||
| 88 |
// invert amountSpecified because v3 swaps use inverted signs |
||
| 89 |
address(this), |
||
| 90 |
zeroForOne, |
||
| 91 |
amountSpecified * -1, |
||
| 92 |
zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT, |
||
| 93 |
"" |
||
| 94 |
); |
||
| 95 |
// v3 can handle bigger numbers than v4, so if we exceed int128, check that the next call reverts |
||
| 96 |
bool overflows = false; |
||
| 97 |
if ( |
||
| 98 |
amount0Delta > type(int128).max || amount1Delta > type(int128).max || amount0Delta < type(int128).min |
||
| 99 |
|| amount1Delta < type(int128).min |
||
| 100 |
) {
|
||
| 101 |
overflows = true; |
||
| 102 |
} |
||
| 103 |
// v4 swap |
||
| 104 |
IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({
|
||
| 105 |
zeroForOne: zeroForOne, |
||
| 106 |
amountSpecified: amountSpecified, |
||
| 107 |
sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT |
||
| 108 |
}); |
||
| 109 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 110 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 111 | |||
| 112 |
BalanceDelta delta; |
||
| 113 |
try swapRouter.swap(key_, swapParams, testSettings, "") returns (BalanceDelta delta_) {
|
||
| 114 |
delta = delta_; |
||
| 115 |
} catch (bytes memory reason) {
|
||
| 116 |
require(overflows, "v4 should not overflow"); |
||
| 117 |
assertEq(bytes4(reason), SafeCast.SafeCastOverflow.selector); |
||
| 118 |
delta = toBalanceDelta(0, 0); |
||
| 119 |
amount0Delta = 0; |
||
| 120 |
amount1Delta = 0; |
||
| 121 |
} |
||
| 122 | |||
| 123 |
// because signs for v3 and v4 swaps are inverted, add values up to get the difference |
||
| 124 |
amount0Diff = amount0Delta + delta.amount0(); |
||
| 125 |
amount1Diff = amount1Delta + delta.amount1(); |
||
| 126 |
} |
||
| 127 | |||
| 128 |
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
|
||
| 129 |
currency0.transfer(msg.sender, amount0Owed); |
||
| 130 |
currency1.transfer(msg.sender, amount1Owed); |
||
| 131 |
} |
||
| 132 | |||
| 133 |
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata) external {
|
||
| 134 |
if (amount0Delta > 0) currency0.transfer(msg.sender, uint256(amount0Delta)); |
||
| 135 |
if (amount1Delta > 0) currency1.transfer(msg.sender, uint256(amount1Delta)); |
||
| 136 |
} |
||
| 137 |
} |
||
| 138 | |||
| 139 |
contract V3SwapTests is V3Fuzzer {
|
||
| 140 |
function test_shouldSwapEqual( |
||
| 141 |
uint24 feeSeed, |
||
| 142 |
int24 tickSpacingSeed, |
||
| 143 |
int24 lowerTickUnsanitized, |
||
| 144 |
int24 upperTickUnsanitized, |
||
| 145 |
int256 liquidityDeltaUnbound, |
||
| 146 |
int256 sqrtPriceX96seed, |
||
| 147 |
int128 swapAmount, |
||
| 148 |
bool zeroForOne |
||
| 149 |
) public {
|
||
| 150 |
(IUniswapV3Pool pool, PoolKey memory key_, uint160 sqrtPriceX96) = |
||
| 151 |
initPools(feeSeed, tickSpacingSeed, sqrtPriceX96seed); |
||
| 152 |
addLiquidity(pool, key_, sqrtPriceX96, lowerTickUnsanitized, upperTickUnsanitized, liquidityDeltaUnbound, false); |
||
| 153 |
(int256 amount0Diff, int256 amount1Diff) = swap(pool, key_, zeroForOne, swapAmount); |
||
| 154 |
assertEq(amount0Diff, 0); |
||
| 155 |
assertEq(amount1Diff, 0); |
||
| 156 |
} |
||
| 157 | |||
| 158 |
struct TightLiquidityParams {
|
||
| 159 |
int24 lowerTickUnsanitized; |
||
| 160 |
int24 upperTickUnsanitized; |
||
| 161 |
int256 liquidityDeltaUnbound; |
||
| 162 |
} |
||
| 163 | |||
| 164 |
function test_shouldSwapEqualMultipleLP( |
||
| 165 |
uint24 feeSeed, |
||
| 166 |
int24 tickSpacingSeed, |
||
| 167 |
TightLiquidityParams[] memory liquidityParams, |
||
| 168 |
int256 sqrtPriceX96seed, |
||
| 169 |
int128 swapAmount, |
||
| 170 |
bool zeroForOne |
||
| 171 |
) public {
|
||
| 172 |
(IUniswapV3Pool pool, PoolKey memory key_, uint160 sqrtPriceX96) = |
||
| 173 |
initPools(feeSeed, tickSpacingSeed, sqrtPriceX96seed); |
||
| 174 |
for (uint256 i = 0; i < liquidityParams.length; ++i) {
|
||
| 175 |
if (i == 20) break; |
||
| 176 |
addLiquidity( |
||
| 177 |
pool, |
||
| 178 |
key_, |
||
| 179 |
sqrtPriceX96, |
||
| 180 |
liquidityParams[i].lowerTickUnsanitized, |
||
| 181 |
liquidityParams[i].upperTickUnsanitized, |
||
| 182 |
liquidityParams[i].liquidityDeltaUnbound, |
||
| 183 |
true |
||
| 184 |
); |
||
| 185 |
} |
||
| 186 | |||
| 187 |
(int256 amount0Diff, int256 amount1Diff) = swap(pool, key_, zeroForOne, swapAmount); |
||
| 188 |
assertEq(amount0Diff, 0); |
||
| 189 |
assertEq(amount1Diff, 0); |
||
| 190 |
} |
||
| 191 |
} |
||
| 192 |
| Lines covered: | 0 / 540 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 6 |
import {Hooks} from "../src/libraries/Hooks.sol";
|
||
| 7 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 8 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 9 |
import {IProtocolFeeController} from "../src/interfaces/IProtocolFeeController.sol";
|
||
| 10 |
import {PoolManager} from "../src/PoolManager.sol";
|
||
| 11 |
import {TickMath} from "../src/libraries/TickMath.sol";
|
||
| 12 |
import {Pool} from "../src/libraries/Pool.sol";
|
||
| 13 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 14 |
import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
|
||
| 15 |
import {MockHooks} from "../src/test/MockHooks.sol";
|
||
| 16 |
import {MockContract} from "../src/test/MockContract.sol";
|
||
| 17 |
import {EmptyTestHooks} from "../src/test/EmptyTestHooks.sol";
|
||
| 18 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 19 |
import {PoolModifyLiquidityTest} from "../src/test/PoolModifyLiquidityTest.sol";
|
||
| 20 |
import {BalanceDelta, BalanceDeltaLibrary} from "../src/types/BalanceDelta.sol";
|
||
| 21 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 22 |
import {PoolSettleTest} from "../src/test/PoolSettleTest.sol";
|
||
| 23 |
import {TestInvalidERC20} from "../src/test/TestInvalidERC20.sol";
|
||
| 24 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 25 |
import {PoolEmptyUnlockTest} from "../src/test/PoolEmptyUnlockTest.sol";
|
||
| 26 |
import {Action} from "../src/test/PoolNestedActionsTest.sol";
|
||
| 27 |
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
|
||
| 28 |
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
|
||
| 29 |
import {Position} from "../src/libraries/Position.sol";
|
||
| 30 |
import {Constants} from "./utils/Constants.sol";
|
||
| 31 |
import {SafeCast} from "../src/libraries/SafeCast.sol";
|
||
| 32 |
// import {AmountHelpers} from "./utils/AmountHelpers.sol";
|
||
| 33 |
import {ProtocolFeeLibrary} from "../src/libraries/ProtocolFeeLibrary.sol";
|
||
| 34 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 35 |
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
|
||
| 36 | |||
| 37 |
contract PoolManagerTest is Test, Deployers, GasSnapshot {
|
||
| 38 |
using Hooks for IHooks; |
||
| 39 |
using PoolIdLibrary for PoolKey; |
||
| 40 |
using LPFeeLibrary for uint24; |
||
| 41 |
using SafeCast for *; |
||
| 42 |
using ProtocolFeeLibrary for uint24; |
||
| 43 |
using StateLibrary for IPoolManager; |
||
| 44 | |||
| 45 |
event UnlockCallback(); |
||
| 46 |
event ProtocolFeeControllerUpdated(address feeController); |
||
| 47 |
event ModifyLiquidity( |
||
| 48 |
PoolId indexed poolId, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta |
||
| 49 |
); |
||
| 50 |
event Swap( |
||
| 51 |
PoolId indexed poolId, |
||
| 52 |
address indexed sender, |
||
| 53 |
int128 amount0, |
||
| 54 |
int128 amount1, |
||
| 55 |
uint160 sqrtPriceX96, |
||
| 56 |
uint128 liquidity, |
||
| 57 |
int24 tick, |
||
| 58 |
uint24 fee |
||
| 59 |
); |
||
| 60 | |||
| 61 |
event Transfer( |
||
| 62 |
address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount |
||
| 63 |
); |
||
| 64 | |||
| 65 |
PoolEmptyUnlockTest emptyUnlockRouter; |
||
| 66 | |||
| 67 |
uint24 constant MAX_PROTOCOL_FEE_BOTH_TOKENS = (1000 << 12) | 1000; // 1000 1000 |
||
| 68 | |||
| 69 |
function setUp() public {
|
||
| 70 |
initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0))); |
||
| 71 | |||
| 72 |
emptyUnlockRouter = new PoolEmptyUnlockTest(manager); |
||
| 73 |
} |
||
| 74 | |||
| 75 |
function test_bytecodeSize() public {
|
||
| 76 |
snapSize("poolManager bytecode size", address(manager));
|
||
| 77 |
} |
||
| 78 | |||
| 79 |
function test_addLiquidity_failsIfNotInitialized() public {
|
||
| 80 |
vm.expectRevert(Pool.PoolNotInitialized.selector); |
||
| 81 |
modifyLiquidityRouter.modifyLiquidity(uninitializedKey, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 82 |
} |
||
| 83 | |||
| 84 |
function test_addLiquidity_failsIfLocked() public {
|
||
| 85 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 86 |
manager.modifyLiquidity(uninitializedKey, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 87 |
} |
||
| 88 | |||
| 89 |
function test_removeLiquidity_failsIfNotInitialized() public {
|
||
| 90 |
vm.expectRevert(Pool.PoolNotInitialized.selector); |
||
| 91 |
modifyLiquidityRouter.modifyLiquidity(uninitializedKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function test_removeLiquidity_failsIfLocked() public {
|
||
| 95 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 96 |
manager.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function test_addLiquidity_succeedsIfInitialized(uint160 sqrtPriceX96) public {
|
||
| 100 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 101 | |||
| 102 |
vm.expectEmit(true, true, true, true); |
||
| 103 |
emit ModifyLiquidity( |
||
| 104 |
key.toId(), |
||
| 105 |
address(modifyLiquidityRouter), |
||
| 106 |
LIQUIDITY_PARAMS.tickLower, |
||
| 107 |
LIQUIDITY_PARAMS.tickUpper, |
||
| 108 |
LIQUIDITY_PARAMS.liquidityDelta |
||
| 109 |
); |
||
| 110 | |||
| 111 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function test_removeLiquidity_succeedsIfInitialized(uint160 sqrtPriceX96) public {
|
||
| 115 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 116 | |||
| 117 |
vm.expectEmit(true, true, true, true); |
||
| 118 |
emit ModifyLiquidity( |
||
| 119 |
key.toId(), |
||
| 120 |
address(modifyLiquidityRouter), |
||
| 121 |
REMOVE_LIQUIDITY_PARAMS.tickLower, |
||
| 122 |
REMOVE_LIQUIDITY_PARAMS.tickUpper, |
||
| 123 |
REMOVE_LIQUIDITY_PARAMS.liquidityDelta |
||
| 124 |
); |
||
| 125 | |||
| 126 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
function test_addLiquidity_succeedsForNativeTokensIfInitialized(uint160 sqrtPriceX96) public {
|
||
| 130 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 131 | |||
| 132 |
vm.expectEmit(true, true, true, true); |
||
| 133 |
emit ModifyLiquidity( |
||
| 134 |
nativeKey.toId(), |
||
| 135 |
address(modifyLiquidityRouter), |
||
| 136 |
LIQUIDITY_PARAMS.tickLower, |
||
| 137 |
LIQUIDITY_PARAMS.tickUpper, |
||
| 138 |
LIQUIDITY_PARAMS.liquidityDelta |
||
| 139 |
); |
||
| 140 | |||
| 141 |
modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, LIQUIDITY_PARAMS, ZERO_BYTES);
|
||
| 142 |
} |
||
| 143 | |||
| 144 |
function test_removeLiquidity_succeedsForNativeTokensIfInitialized(uint160 sqrtPriceX96) public {
|
||
| 145 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 146 | |||
| 147 |
vm.expectEmit(true, true, true, true); |
||
| 148 |
emit ModifyLiquidity( |
||
| 149 |
nativeKey.toId(), |
||
| 150 |
address(modifyLiquidityRouter), |
||
| 151 |
REMOVE_LIQUIDITY_PARAMS.tickLower, |
||
| 152 |
REMOVE_LIQUIDITY_PARAMS.tickUpper, |
||
| 153 |
REMOVE_LIQUIDITY_PARAMS.liquidityDelta |
||
| 154 |
); |
||
| 155 | |||
| 156 |
modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
|
||
| 157 |
} |
||
| 158 | |||
| 159 |
function test_addLiquidity_succeedsWithHooksIfInitialized(uint160 sqrtPriceX96) public {
|
||
| 160 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 161 | |||
| 162 |
address payable mockAddr = |
||
| 163 |
payable(address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG))); |
||
| 164 |
address payable hookAddr = payable(Constants.ALL_HOOKS); |
||
| 165 | |||
| 166 |
vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
|
||
| 167 |
MockContract mockContract = new MockContract(); |
||
| 168 |
vm.etch(mockAddr, address(mockContract).code); |
||
| 169 | |||
| 170 |
MockContract(mockAddr).setImplementation(hookAddr); |
||
| 171 | |||
| 172 |
(key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES); |
||
| 173 | |||
| 174 |
BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 175 | |||
| 176 |
bytes32 beforeSelector = MockHooks.beforeAddLiquidity.selector; |
||
| 177 |
bytes memory beforeParams = abi.encode(address(modifyLiquidityRouter), key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 178 |
bytes32 afterSelector = MockHooks.afterAddLiquidity.selector; |
||
| 179 |
bytes memory afterParams = |
||
| 180 |
abi.encode(address(modifyLiquidityRouter), key, LIQUIDITY_PARAMS, balanceDelta, ZERO_BYTES); |
||
| 181 | |||
| 182 |
assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1); |
||
| 183 |
assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams)); |
||
| 184 |
assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1); |
||
| 185 |
assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams)); |
||
| 186 |
} |
||
| 187 | |||
| 188 |
function test_removeLiquidity_succeedsWithHooksIfInitialized(uint160 sqrtPriceX96) public {
|
||
| 189 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 190 | |||
| 191 |
address payable mockAddr = |
||
| 192 |
payable(address(uint160(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG))); |
||
| 193 |
address payable hookAddr = payable(Constants.ALL_HOOKS); |
||
| 194 | |||
| 195 |
vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
|
||
| 196 |
MockContract mockContract = new MockContract(); |
||
| 197 |
vm.etch(mockAddr, address(mockContract).code); |
||
| 198 | |||
| 199 |
MockContract(mockAddr).setImplementation(hookAddr); |
||
| 200 | |||
| 201 |
(key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES); |
||
| 202 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 203 |
BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 204 | |||
| 205 |
bytes32 beforeSelector = MockHooks.beforeRemoveLiquidity.selector; |
||
| 206 |
bytes memory beforeParams = abi.encode(address(modifyLiquidityRouter), key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 207 |
bytes32 afterSelector = MockHooks.afterRemoveLiquidity.selector; |
||
| 208 |
bytes memory afterParams = |
||
| 209 |
abi.encode(address(modifyLiquidityRouter), key, REMOVE_LIQUIDITY_PARAMS, balanceDelta, ZERO_BYTES); |
||
| 210 | |||
| 211 |
assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1); |
||
| 212 |
assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams)); |
||
| 213 |
assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1); |
||
| 214 |
assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams)); |
||
| 215 |
} |
||
| 216 | |||
| 217 |
function test_addLiquidity_failsWithIncorrectSelectors() public {
|
||
| 218 |
address hookAddr = address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 219 | |||
| 220 |
MockHooks impl = new MockHooks(); |
||
| 221 |
vm.etch(hookAddr, address(impl).code); |
||
| 222 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 223 | |||
| 224 |
(key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 225 | |||
| 226 |
mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 227 |
mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 228 | |||
| 229 |
// Fails at beforeAddLiquidity hook. |
||
| 230 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 231 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 232 | |||
| 233 |
// Fail at afterAddLiquidity hook. |
||
| 234 |
mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, mockHooks.beforeAddLiquidity.selector); |
||
| 235 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 236 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 237 |
} |
||
| 238 | |||
| 239 |
function test_removeLiquidity_failsWithIncorrectSelectors() public {
|
||
| 240 |
address hookAddr = address(uint160(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 241 | |||
| 242 |
MockHooks impl = new MockHooks(); |
||
| 243 |
vm.etch(hookAddr, address(impl).code); |
||
| 244 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 245 | |||
| 246 |
(key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 247 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 248 | |||
| 249 |
mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 250 |
mockHooks.setReturnValue(mockHooks.afterRemoveLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 251 | |||
| 252 |
// Fails at beforeRemoveLiquidity hook. |
||
| 253 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 254 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 255 | |||
| 256 |
// Fail at afterRemoveLiquidity hook. |
||
| 257 |
mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, mockHooks.beforeRemoveLiquidity.selector); |
||
| 258 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 259 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 260 |
} |
||
| 261 | |||
| 262 |
function test_addLiquidity_succeedsWithCorrectSelectors() public {
|
||
| 263 |
address hookAddr = address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 264 | |||
| 265 |
MockHooks impl = new MockHooks(); |
||
| 266 |
vm.etch(hookAddr, address(impl).code); |
||
| 267 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 268 | |||
| 269 |
(key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 270 | |||
| 271 |
mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, mockHooks.beforeAddLiquidity.selector); |
||
| 272 |
mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, mockHooks.afterAddLiquidity.selector); |
||
| 273 | |||
| 274 |
vm.expectEmit(true, true, true, true); |
||
| 275 |
emit ModifyLiquidity( |
||
| 276 |
key.toId(), |
||
| 277 |
address(modifyLiquidityRouter), |
||
| 278 |
LIQUIDITY_PARAMS.tickLower, |
||
| 279 |
LIQUIDITY_PARAMS.tickUpper, |
||
| 280 |
LIQUIDITY_PARAMS.liquidityDelta |
||
| 281 |
); |
||
| 282 | |||
| 283 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 284 |
} |
||
| 285 | |||
| 286 |
function test_removeLiquidity_succeedsWithCorrectSelectors() public {
|
||
| 287 |
address hookAddr = address(uint160(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 288 | |||
| 289 |
MockHooks impl = new MockHooks(); |
||
| 290 |
vm.etch(hookAddr, address(impl).code); |
||
| 291 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 292 | |||
| 293 |
(key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 294 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 295 | |||
| 296 |
mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, mockHooks.beforeRemoveLiquidity.selector); |
||
| 297 |
mockHooks.setReturnValue(mockHooks.afterRemoveLiquidity.selector, mockHooks.afterRemoveLiquidity.selector); |
||
| 298 | |||
| 299 |
vm.expectEmit(true, true, true, true); |
||
| 300 |
emit ModifyLiquidity( |
||
| 301 |
key.toId(), |
||
| 302 |
address(modifyLiquidityRouter), |
||
| 303 |
REMOVE_LIQUIDITY_PARAMS.tickLower, |
||
| 304 |
REMOVE_LIQUIDITY_PARAMS.tickUpper, |
||
| 305 |
REMOVE_LIQUIDITY_PARAMS.liquidityDelta |
||
| 306 |
); |
||
| 307 | |||
| 308 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 309 |
} |
||
| 310 | |||
| 311 |
function test_addLiquidity_6909() public {
|
||
| 312 |
// convert test tokens into ERC6909 claims |
||
| 313 |
claimsRouter.deposit(currency0, address(this), 10_000e18); |
||
| 314 |
claimsRouter.deposit(currency1, address(this), 10_000e18); |
||
| 315 |
assertEq(manager.balanceOf(address(this), currency0.toId()), 10_000e18); |
||
| 316 |
assertEq(manager.balanceOf(address(this), currency1.toId()), 10_000e18); |
||
| 317 | |||
| 318 |
uint256 currency0BalanceBefore = currency0.balanceOfSelf(); |
||
| 319 |
uint256 currency1BalanceBefore = currency1.balanceOfSelf(); |
||
| 320 |
uint256 currency0PMBalanceBefore = currency0.balanceOf(address(manager)); |
||
| 321 |
uint256 currency1PMBalanceBefore = currency1.balanceOf(address(manager)); |
||
| 322 | |||
| 323 |
// allow liquidity router to burn our 6909 tokens |
||
| 324 |
manager.setOperator(address(modifyLiquidityRouter), true); |
||
| 325 | |||
| 326 |
// add liquidity with 6909: settleUsingBurn=true, takeClaims=true (unused) |
||
| 327 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES, true, true); |
||
| 328 | |||
| 329 |
assertLt(manager.balanceOf(address(this), currency0.toId()), 10_000e18); |
||
| 330 |
assertLt(manager.balanceOf(address(this), currency1.toId()), 10_000e18); |
||
| 331 | |||
| 332 |
// ERC20s are unspent |
||
| 333 |
assertEq(currency0.balanceOfSelf(), currency0BalanceBefore); |
||
| 334 |
assertEq(currency1.balanceOfSelf(), currency1BalanceBefore); |
||
| 335 | |||
| 336 |
// PoolManager did not receive net-new ERC20s |
||
| 337 |
assertEq(currency0.balanceOf(address(manager)), currency0PMBalanceBefore); |
||
| 338 |
assertEq(currency1.balanceOf(address(manager)), currency1PMBalanceBefore); |
||
| 339 |
} |
||
| 340 | |||
| 341 |
function test_removeLiquidity_6909() public {
|
||
| 342 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 343 | |||
| 344 |
assertEq(manager.balanceOf(address(this), currency0.toId()), 0); |
||
| 345 |
assertEq(manager.balanceOf(address(this), currency1.toId()), 0); |
||
| 346 | |||
| 347 |
uint256 currency0BalanceBefore = currency0.balanceOfSelf(); |
||
| 348 |
uint256 currency1BalanceBefore = currency1.balanceOfSelf(); |
||
| 349 |
uint256 currency0PMBalanceBefore = currency0.balanceOf(address(manager)); |
||
| 350 |
uint256 currency1PMBalanceBefore = currency1.balanceOf(address(manager)); |
||
| 351 | |||
| 352 |
// remove liquidity as 6909: settleUsingBurn=true (unused), takeClaims=true |
||
| 353 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES, true, true); |
||
| 354 | |||
| 355 |
assertTrue(manager.balanceOf(address(this), currency0.toId()) > 0); |
||
| 356 |
assertTrue(manager.balanceOf(address(this), currency1.toId()) > 0); |
||
| 357 | |||
| 358 |
// ERC20s are unspent |
||
| 359 |
assertEq(currency0.balanceOfSelf(), currency0BalanceBefore); |
||
| 360 |
assertEq(currency1.balanceOfSelf(), currency1BalanceBefore); |
||
| 361 | |||
| 362 |
// PoolManager did lose ERC-20s |
||
| 363 |
assertEq(currency0.balanceOf(address(manager)), currency0PMBalanceBefore); |
||
| 364 |
assertEq(currency1.balanceOf(address(manager)), currency1PMBalanceBefore); |
||
| 365 |
} |
||
| 366 | |||
| 367 |
function test_addLiquidity_gas() public {
|
||
| 368 |
IPoolManager.ModifyLiquidityParams memory uniqueParams = |
||
| 369 |
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
|
||
| 370 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 371 |
snapLastCall("simple addLiquidity");
|
||
| 372 |
} |
||
| 373 | |||
| 374 |
function test_addLiquidity_secondAdditionSameRange_gas() public {
|
||
| 375 |
IPoolManager.ModifyLiquidityParams memory uniqueParams = |
||
| 376 |
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
|
||
| 377 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 378 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 379 |
snapLastCall("simple addLiquidity second addition same range");
|
||
| 380 |
} |
||
| 381 | |||
| 382 |
function test_removeLiquidity_gas() public {
|
||
| 383 |
IPoolManager.ModifyLiquidityParams memory uniqueParams = |
||
| 384 |
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
|
||
| 385 |
// add some liquidity to remove |
||
| 386 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 387 | |||
| 388 |
uniqueParams.liquidityDelta *= -1; |
||
| 389 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 390 |
snapLastCall("simple removeLiquidity");
|
||
| 391 |
} |
||
| 392 | |||
| 393 |
function test_removeLiquidity_someLiquidityRemains_gas() public {
|
||
| 394 |
// add double the liquidity to remove |
||
| 395 |
IPoolManager.ModifyLiquidityParams memory uniqueParams = |
||
| 396 |
IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
|
||
| 397 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 398 | |||
| 399 |
uniqueParams.liquidityDelta /= -2; |
||
| 400 |
modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES); |
||
| 401 |
snapLastCall("simple removeLiquidity some liquidity remains");
|
||
| 402 |
} |
||
| 403 | |||
| 404 |
function test_addLiquidity_succeeds() public {
|
||
| 405 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 406 |
} |
||
| 407 | |||
| 408 |
function test_removeLiquidity_succeeds() public {
|
||
| 409 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 410 |
} |
||
| 411 | |||
| 412 |
function test_addLiquidity_withNative_gas() public {
|
||
| 413 |
modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, LIQUIDITY_PARAMS, ZERO_BYTES);
|
||
| 414 |
snapLastCall("addLiquidity with native token");
|
||
| 415 |
} |
||
| 416 | |||
| 417 |
function test_removeLiquidity_withNative_gas() public {
|
||
| 418 |
modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
|
||
| 419 |
snapLastCall("removeLiquidity with native token");
|
||
| 420 |
} |
||
| 421 | |||
| 422 |
function test_addLiquidity_withHooks_gas() public {
|
||
| 423 |
address allHooksAddr = Constants.ALL_HOOKS; |
||
| 424 |
MockHooks impl = new MockHooks(); |
||
| 425 |
vm.etch(allHooksAddr, address(impl).code); |
||
| 426 |
MockHooks mockHooks = MockHooks(allHooksAddr); |
||
| 427 | |||
| 428 |
(key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 429 | |||
| 430 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 431 |
snapLastCall("addLiquidity with empty hook");
|
||
| 432 |
} |
||
| 433 | |||
| 434 |
function test_removeLiquidity_withHooks_gas() public {
|
||
| 435 |
address allHooksAddr = Constants.ALL_HOOKS; |
||
| 436 |
MockHooks impl = new MockHooks(); |
||
| 437 |
vm.etch(allHooksAddr, address(impl).code); |
||
| 438 |
MockHooks mockHooks = MockHooks(allHooksAddr); |
||
| 439 | |||
| 440 |
(key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 441 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 442 | |||
| 443 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 444 |
snapLastCall("removeLiquidity with empty hook");
|
||
| 445 |
} |
||
| 446 | |||
| 447 |
function test_swap_failsIfNotInitialized(uint160 sqrtPriceX96) public {
|
||
| 448 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 449 | |||
| 450 |
key.fee = 100; |
||
| 451 |
IPoolManager.SwapParams memory params = |
||
| 452 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: sqrtPriceX96});
|
||
| 453 | |||
| 454 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 455 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 456 | |||
| 457 |
vm.expectRevert(Pool.PoolNotInitialized.selector); |
||
| 458 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 459 |
} |
||
| 460 | |||
| 461 |
function test_swap_succeedsIfInitialized() public {
|
||
| 462 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 463 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 464 | |||
| 465 |
vm.expectEmit(true, true, true, true); |
||
| 466 |
emit Swap( |
||
| 467 |
key.toId(), address(swapRouter), int128(-100), int128(98), 79228162514264329749955861424, 1e18, -1, 3000 |
||
| 468 |
); |
||
| 469 | |||
| 470 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 471 |
} |
||
| 472 | |||
| 473 |
function test_swap_failsIfLocked() public {
|
||
| 474 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 475 |
manager.swap(key, SWAP_PARAMS, ZERO_BYTES); |
||
| 476 |
} |
||
| 477 | |||
| 478 |
function test_swap_succeedsWithNativeTokensIfInitialized() public {
|
||
| 479 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 480 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 481 | |||
| 482 |
vm.expectEmit(true, true, true, true); |
||
| 483 |
emit Swap( |
||
| 484 |
nativeKey.toId(), |
||
| 485 |
address(swapRouter), |
||
| 486 |
int128(-100), |
||
| 487 |
int128(98), |
||
| 488 |
79228162514264329749955861424, |
||
| 489 |
1e18, |
||
| 490 |
-1, |
||
| 491 |
3000 |
||
| 492 |
); |
||
| 493 | |||
| 494 |
swapRouter.swap{value: 100}(nativeKey, SWAP_PARAMS, testSettings, ZERO_BYTES);
|
||
| 495 |
} |
||
| 496 | |||
| 497 |
function test_swap_succeedsWithHooksIfInitialized() public {
|
||
| 498 |
address payable mockAddr = payable(address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG))); |
||
| 499 |
address payable hookAddr = payable(Constants.ALL_HOOKS); |
||
| 500 | |||
| 501 |
vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
|
||
| 502 |
MockContract mockContract = new MockContract(); |
||
| 503 |
vm.etch(mockAddr, address(mockContract).code); |
||
| 504 | |||
| 505 |
MockContract(mockAddr).setImplementation(hookAddr); |
||
| 506 | |||
| 507 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(mockAddr), 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 508 | |||
| 509 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 510 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 511 | |||
| 512 |
BalanceDelta balanceDelta = swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 513 | |||
| 514 |
bytes32 beforeSelector = MockHooks.beforeSwap.selector; |
||
| 515 |
bytes memory beforeParams = abi.encode(address(swapRouter), key, SWAP_PARAMS, ZERO_BYTES); |
||
| 516 | |||
| 517 |
bytes32 afterSelector = MockHooks.afterSwap.selector; |
||
| 518 |
bytes memory afterParams = abi.encode(address(swapRouter), key, SWAP_PARAMS, balanceDelta, ZERO_BYTES); |
||
| 519 | |||
| 520 |
assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1); |
||
| 521 |
assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams)); |
||
| 522 |
assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1); |
||
| 523 |
assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams)); |
||
| 524 |
} |
||
| 525 | |||
| 526 |
function test_swap_failsWithIncorrectSelectors() public {
|
||
| 527 |
address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG)); |
||
| 528 | |||
| 529 |
MockHooks impl = new MockHooks(); |
||
| 530 |
vm.etch(hookAddr, address(impl).code); |
||
| 531 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 532 | |||
| 533 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 534 | |||
| 535 |
IPoolManager.SwapParams memory swapParams = |
||
| 536 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 10, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 537 | |||
| 538 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 539 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 540 | |||
| 541 |
mockHooks.setReturnValue(mockHooks.beforeSwap.selector, bytes4(0xdeadbeef)); |
||
| 542 |
mockHooks.setReturnValue(mockHooks.afterSwap.selector, bytes4(0xdeadbeef)); |
||
| 543 | |||
| 544 |
// Fails at beforeSwap hook. |
||
| 545 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 546 |
swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES); |
||
| 547 | |||
| 548 |
// Fail at afterSwap hook. |
||
| 549 |
mockHooks.setReturnValue(mockHooks.beforeSwap.selector, mockHooks.beforeSwap.selector); |
||
| 550 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 551 |
swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES); |
||
| 552 |
} |
||
| 553 | |||
| 554 |
function test_swap_succeedsWithCorrectSelectors() public {
|
||
| 555 |
address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG)); |
||
| 556 | |||
| 557 |
MockHooks impl = new MockHooks(); |
||
| 558 |
vm.etch(hookAddr, address(impl).code); |
||
| 559 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 560 | |||
| 561 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 562 | |||
| 563 |
IPoolManager.SwapParams memory swapParams = |
||
| 564 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -10, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 565 | |||
| 566 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 567 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 568 | |||
| 569 |
mockHooks.setReturnValue(mockHooks.beforeSwap.selector, mockHooks.beforeSwap.selector); |
||
| 570 |
mockHooks.setReturnValue(mockHooks.afterSwap.selector, mockHooks.afterSwap.selector); |
||
| 571 | |||
| 572 |
vm.expectEmit(true, true, true, true); |
||
| 573 |
emit Swap(key.toId(), address(swapRouter), -10, 8, 79228162514264336880490487708, 1e18, -1, 100); |
||
| 574 | |||
| 575 |
swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES); |
||
| 576 |
} |
||
| 577 | |||
| 578 |
function test_swap_succeeds() public {
|
||
| 579 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 580 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 581 | |||
| 582 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 583 |
} |
||
| 584 | |||
| 585 |
function test_swap_gas() public {
|
||
| 586 |
swapRouterNoChecks.swap(key, SWAP_PARAMS); |
||
| 587 |
snapLastCall("simple swap");
|
||
| 588 |
} |
||
| 589 | |||
| 590 |
function test_swap_withNative_succeeds() public {
|
||
| 591 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 592 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 593 | |||
| 594 |
swapRouter.swap{value: 100}(nativeKey, SWAP_PARAMS, testSettings, ZERO_BYTES);
|
||
| 595 |
} |
||
| 596 | |||
| 597 |
function test_swap_withNative_gas() public {
|
||
| 598 |
swapRouterNoChecks.swap{value: 100}(nativeKey, SWAP_PARAMS);
|
||
| 599 |
snapLastCall("simple swap with native");
|
||
| 600 |
} |
||
| 601 | |||
| 602 |
function test_swap_withHooks_gas() public {
|
||
| 603 |
address allHooksAddr = Constants.ALL_HOOKS; |
||
| 604 | |||
| 605 |
MockHooks impl = new MockHooks(); |
||
| 606 |
vm.etch(allHooksAddr, address(impl).code); |
||
| 607 |
MockHooks mockHooks = MockHooks(allHooksAddr); |
||
| 608 | |||
| 609 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 610 | |||
| 611 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 612 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 613 | |||
| 614 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 615 | |||
| 616 |
IPoolManager.SwapParams memory swapParams = |
||
| 617 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_4});
|
||
| 618 |
testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 619 | |||
| 620 |
swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES); |
||
| 621 |
snapLastCall("swap with hooks");
|
||
| 622 |
} |
||
| 623 | |||
| 624 |
function test_swap_mint6909IfOutputNotTaken_gas() public {
|
||
| 625 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 626 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 627 | |||
| 628 |
vm.expectEmit(); |
||
| 629 |
emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(currency1), 98); |
||
| 630 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 631 |
snapLastCall("swap mint output as 6909");
|
||
| 632 | |||
| 633 |
uint256 erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(currency1)); |
||
| 634 |
assertEq(erc6909Balance, 98); |
||
| 635 |
} |
||
| 636 | |||
| 637 |
function test_swap_mint6909IfNativeOutputNotTaken_gas() public {
|
||
| 638 |
IPoolManager.SwapParams memory params = |
||
| 639 |
IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_2_1});
|
||
| 640 | |||
| 641 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 642 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 643 | |||
| 644 |
vm.expectEmit(); |
||
| 645 |
emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE), 98); |
||
| 646 |
swapRouter.swap(nativeKey, params, testSettings, ZERO_BYTES); |
||
| 647 |
snapLastCall("swap mint native output as 6909");
|
||
| 648 | |||
| 649 |
uint256 erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE)); |
||
| 650 |
assertEq(erc6909Balance, 98); |
||
| 651 |
} |
||
| 652 | |||
| 653 |
function test_swap_burn6909AsInput_gas() public {
|
||
| 654 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 655 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 656 | |||
| 657 |
vm.expectEmit(); |
||
| 658 |
emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(currency1), 98); |
||
| 659 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 660 | |||
| 661 |
uint256 erc6909Balance = manager.balanceOf(address(this), uint256(uint160(Currency.unwrap(currency1)))); |
||
| 662 |
assertEq(erc6909Balance, 98); |
||
| 663 | |||
| 664 |
// give permission for swapRouter to burn the 6909s |
||
| 665 |
manager.setOperator(address(swapRouter), true); |
||
| 666 | |||
| 667 |
// swap from currency1 to currency0 again, using 6909s as input tokens |
||
| 668 |
IPoolManager.SwapParams memory params = |
||
| 669 |
IPoolManager.SwapParams({zeroForOne: false, amountSpecified: 25, sqrtPriceLimitX96: SQRT_PRICE_4_1});
|
||
| 670 |
testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: true});
|
||
| 671 | |||
| 672 |
vm.expectEmit(); |
||
| 673 |
emit Transfer(address(swapRouter), address(this), address(0), CurrencyLibrary.toId(currency1), 27); |
||
| 674 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 675 |
snapLastCall("swap burn 6909 for input");
|
||
| 676 | |||
| 677 |
erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(currency1)); |
||
| 678 |
assertEq(erc6909Balance, 71); |
||
| 679 |
} |
||
| 680 | |||
| 681 |
function test_swap_burnNative6909AsInput_gas() public {
|
||
| 682 |
IPoolManager.SwapParams memory params = |
||
| 683 |
IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_2_1});
|
||
| 684 | |||
| 685 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 686 |
PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
|
||
| 687 | |||
| 688 |
vm.expectEmit(); |
||
| 689 |
emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE), 98); |
||
| 690 |
swapRouter.swap(nativeKey, params, testSettings, ZERO_BYTES); |
||
| 691 | |||
| 692 |
uint256 erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE)); |
||
| 693 |
assertEq(erc6909Balance, 98); |
||
| 694 | |||
| 695 |
// give permission for swapRouter to burn the 6909s |
||
| 696 |
manager.setOperator(address(swapRouter), true); |
||
| 697 | |||
| 698 |
// swap from currency0 to currency1, using 6909s as input tokens |
||
| 699 |
params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 25, sqrtPriceLimitX96: SQRT_PRICE_1_4});
|
||
| 700 |
testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: true});
|
||
| 701 | |||
| 702 |
vm.expectEmit(); |
||
| 703 |
emit Transfer(address(swapRouter), address(this), address(0), CurrencyLibrary.toId(CurrencyLibrary.NATIVE), 27); |
||
| 704 |
// don't have to send in native currency since burning 6909 for input |
||
| 705 |
swapRouter.swap(nativeKey, params, testSettings, ZERO_BYTES); |
||
| 706 |
snapLastCall("swap burn native 6909 for input");
|
||
| 707 | |||
| 708 |
erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE)); |
||
| 709 |
assertEq(erc6909Balance, 71); |
||
| 710 |
} |
||
| 711 | |||
| 712 |
function test_swap_againstLiquidity_gas() public {
|
||
| 713 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 714 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 715 | |||
| 716 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES); |
||
| 717 | |||
| 718 |
IPoolManager.SwapParams memory params = |
||
| 719 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_4});
|
||
| 720 | |||
| 721 |
swapRouter.swap(key, params, testSettings, ZERO_BYTES); |
||
| 722 |
snapLastCall("swap against liquidity");
|
||
| 723 |
} |
||
| 724 | |||
| 725 |
function test_swap_againstLiqWithNative_gas() public {
|
||
| 726 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 727 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 728 | |||
| 729 |
swapRouter.swap{value: 1 ether}(nativeKey, SWAP_PARAMS, testSettings, ZERO_BYTES);
|
||
| 730 | |||
| 731 |
IPoolManager.SwapParams memory params = |
||
| 732 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_4});
|
||
| 733 | |||
| 734 |
swapRouter.swap{value: 1 ether}(nativeKey, params, testSettings, ZERO_BYTES);
|
||
| 735 |
snapLastCall("swap against liquidity with native token");
|
||
| 736 |
} |
||
| 737 | |||
| 738 |
function test_swap_accruesProtocolFees(uint16 protocolFee0, uint16 protocolFee1, int256 amountSpecified) public {
|
||
| 739 |
protocolFee0 = uint16(bound(protocolFee0, 0, 1000)); |
||
| 740 |
protocolFee1 = uint16(bound(protocolFee1, 0, 1000)); |
||
| 741 |
vm.assume(amountSpecified != 0); |
||
| 742 | |||
| 743 |
uint24 protocolFee = (uint24(protocolFee1) << 12) | uint24(protocolFee0); |
||
| 744 | |||
| 745 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 746 |
assertEq(slot0ProtocolFee, 0); |
||
| 747 | |||
| 748 |
vm.prank(address(feeController)); |
||
| 749 |
manager.setProtocolFee(key, protocolFee); |
||
| 750 | |||
| 751 |
(,, slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 752 |
assertEq(slot0ProtocolFee, protocolFee); |
||
| 753 | |||
| 754 |
// Add liquidity - Fees dont accrue for positive liquidity delta. |
||
| 755 |
IPoolManager.ModifyLiquidityParams memory params = LIQUIDITY_PARAMS; |
||
| 756 |
modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES); |
||
| 757 | |||
| 758 |
assertEq(manager.protocolFeesAccrued(currency0), 0); |
||
| 759 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 760 | |||
| 761 |
// Remove liquidity - Fees dont accrue for negative liquidity delta. |
||
| 762 |
params.liquidityDelta = -LIQUIDITY_PARAMS.liquidityDelta; |
||
| 763 |
modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES); |
||
| 764 | |||
| 765 |
assertEq(manager.protocolFeesAccrued(currency0), 0); |
||
| 766 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 767 | |||
| 768 |
// Now re-add the liquidity to test swap |
||
| 769 |
params.liquidityDelta = LIQUIDITY_PARAMS.liquidityDelta; |
||
| 770 |
modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES); |
||
| 771 | |||
| 772 |
IPoolManager.SwapParams memory swapParams = |
||
| 773 |
IPoolManager.SwapParams(false, amountSpecified, TickMath.MAX_SQRT_PRICE - 1); |
||
| 774 |
BalanceDelta delta = swapRouter.swap(key, swapParams, PoolSwapTest.TestSettings(false, false), ZERO_BYTES); |
||
| 775 |
uint256 expectedProtocolFee = |
||
| 776 |
uint256(uint128(-delta.amount1())) * protocolFee1 / ProtocolFeeLibrary.PIPS_DENOMINATOR; |
||
| 777 |
assertEq(manager.protocolFeesAccrued(currency0), 0); |
||
| 778 |
assertEq(manager.protocolFeesAccrued(currency1), expectedProtocolFee); |
||
| 779 |
} |
||
| 780 | |||
| 781 |
function test_donate_failsIfNotInitialized() public {
|
||
| 782 |
vm.expectRevert(Pool.PoolNotInitialized.selector); |
||
| 783 |
donateRouter.donate(uninitializedKey, 100, 100, ZERO_BYTES); |
||
| 784 |
} |
||
| 785 | |||
| 786 |
function test_donate_failsIfLocked() public {
|
||
| 787 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 788 |
manager.donate(key, 100, 100, ZERO_BYTES); |
||
| 789 |
} |
||
| 790 | |||
| 791 |
function test_donate_failsIfNoLiquidity(uint160 sqrtPriceX96) public {
|
||
| 792 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 793 | |||
| 794 |
(key,) = initPool(currency0, currency1, IHooks(address(0)), 100, sqrtPriceX96, ZERO_BYTES); |
||
| 795 | |||
| 796 |
vm.expectRevert(Pool.NoLiquidityToReceiveFees.selector); |
||
| 797 |
donateRouter.donate(key, 100, 100, ZERO_BYTES); |
||
| 798 |
} |
||
| 799 | |||
| 800 |
// test successful donation if pool has liquidity |
||
| 801 |
function test_donate_succeedsWhenPoolHasLiquidity() public {
|
||
| 802 |
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(key.toId()); |
||
| 803 |
assertEq(feeGrowthGlobal0X128, 0); |
||
| 804 |
assertEq(feeGrowthGlobal1X128, 0); |
||
| 805 | |||
| 806 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 807 |
snapLastCall("donate gas with 2 tokens");
|
||
| 808 | |||
| 809 |
(feeGrowthGlobal0X128, feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(key.toId()); |
||
| 810 |
assertEq(feeGrowthGlobal0X128, 34028236692093846346337); |
||
| 811 |
assertEq(feeGrowthGlobal1X128, 68056473384187692692674); |
||
| 812 |
} |
||
| 813 | |||
| 814 |
function test_donate_succeedsForNativeTokensWhenPoolHasLiquidity() public {
|
||
| 815 |
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(nativeKey.toId()); |
||
| 816 |
assertEq(feeGrowthGlobal0X128, 0); |
||
| 817 |
assertEq(feeGrowthGlobal1X128, 0); |
||
| 818 | |||
| 819 |
donateRouter.donate{value: 100}(nativeKey, 100, 200, ZERO_BYTES);
|
||
| 820 | |||
| 821 |
(feeGrowthGlobal0X128, feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(nativeKey.toId()); |
||
| 822 |
assertEq(feeGrowthGlobal0X128, 34028236692093846346337); |
||
| 823 |
assertEq(feeGrowthGlobal1X128, 68056473384187692692674); |
||
| 824 |
} |
||
| 825 | |||
| 826 |
function test_donate_failsWithIncorrectSelectors() public {
|
||
| 827 |
address hookAddr = address(uint160(Hooks.BEFORE_DONATE_FLAG | Hooks.AFTER_DONATE_FLAG)); |
||
| 828 | |||
| 829 |
MockHooks impl = new MockHooks(); |
||
| 830 |
vm.etch(hookAddr, address(impl).code); |
||
| 831 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 832 | |||
| 833 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 834 | |||
| 835 |
mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef)); |
||
| 836 |
mockHooks.setReturnValue(mockHooks.afterDonate.selector, bytes4(0xdeadbeef)); |
||
| 837 | |||
| 838 |
// Fails at beforeDonate hook. |
||
| 839 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 840 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 841 | |||
| 842 |
// Fail at afterDonate hook. |
||
| 843 |
mockHooks.setReturnValue(mockHooks.beforeDonate.selector, mockHooks.beforeDonate.selector); |
||
| 844 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 845 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 846 |
} |
||
| 847 | |||
| 848 |
function test_donate_succeedsWithCorrectSelectors() public {
|
||
| 849 |
address hookAddr = address(uint160(Hooks.BEFORE_DONATE_FLAG | Hooks.AFTER_DONATE_FLAG)); |
||
| 850 | |||
| 851 |
MockHooks impl = new MockHooks(); |
||
| 852 |
vm.etch(hookAddr, address(impl).code); |
||
| 853 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 854 | |||
| 855 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 856 | |||
| 857 |
mockHooks.setReturnValue(mockHooks.beforeDonate.selector, mockHooks.beforeDonate.selector); |
||
| 858 |
mockHooks.setReturnValue(mockHooks.afterDonate.selector, mockHooks.afterDonate.selector); |
||
| 859 | |||
| 860 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 861 |
} |
||
| 862 | |||
| 863 |
function test_donate_OneToken_gas() public {
|
||
| 864 |
donateRouter.donate(key, 100, 0, ZERO_BYTES); |
||
| 865 |
snapLastCall("donate gas with 1 token");
|
||
| 866 |
} |
||
| 867 | |||
| 868 |
function test_take_failsWithNoLiquidity() public {
|
||
| 869 |
deployFreshManagerAndRouters(); |
||
| 870 | |||
| 871 |
vm.expectRevert(); |
||
| 872 |
takeRouter.take(key, 100, 0); |
||
| 873 |
} |
||
| 874 | |||
| 875 |
function test_take_failsWithInvalidTokensThatDoNotReturnTrueOnTransfer() public {
|
||
| 876 |
TestInvalidERC20 invalidToken = new TestInvalidERC20(2 ** 255); |
||
| 877 |
Currency invalidCurrency = Currency.wrap(address(invalidToken)); |
||
| 878 |
invalidToken.approve(address(modifyLiquidityRouter), type(uint256).max); |
||
| 879 |
invalidToken.approve(address(takeRouter), type(uint256).max); |
||
| 880 | |||
| 881 |
bool currency0Invalid = invalidCurrency < currency0; |
||
| 882 | |||
| 883 |
(key,) = initPoolAndAddLiquidity( |
||
| 884 |
(currency0Invalid ? invalidCurrency : currency0), |
||
| 885 |
(currency0Invalid ? currency0 : invalidCurrency), |
||
| 886 |
IHooks(address(0)), |
||
| 887 |
3000, |
||
| 888 |
SQRT_PRICE_1_1, |
||
| 889 |
ZERO_BYTES |
||
| 890 |
); |
||
| 891 | |||
| 892 |
(uint256 amount0, uint256 amount1) = currency0Invalid ? (1, 0) : (0, 1); |
||
| 893 |
vm.expectRevert(abi.encodeWithSelector(CurrencyLibrary.ERC20TransferFailed.selector, abi.encode(bytes32(0)))); |
||
| 894 |
takeRouter.take(key, amount0, amount1); |
||
| 895 | |||
| 896 |
// should not revert when non zero amount passed in for valid currency |
||
| 897 |
// assertions inside takeRouter because it takes then settles |
||
| 898 |
(amount0, amount1) = currency0Invalid ? (0, 1) : (1, 0); |
||
| 899 |
takeRouter.take(key, amount0, amount1); |
||
| 900 |
} |
||
| 901 | |||
| 902 |
function test_take_succeedsWithPoolWithLiquidity() public {
|
||
| 903 |
takeRouter.take(key, 1, 1); // assertions inside takeRouter because it takes then settles |
||
| 904 |
} |
||
| 905 | |||
| 906 |
function test_take_failsIfLocked() public {
|
||
| 907 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 908 |
manager.take(key.currency0, address(this), 1); |
||
| 909 |
} |
||
| 910 | |||
| 911 |
function test_take_succeedsWithPoolWithLiquidityWithNativeToken() public {
|
||
| 912 |
takeRouter.take{value: 1}(nativeKey, 1, 1); // assertions inside takeRouter because it takes then settles
|
||
| 913 |
} |
||
| 914 | |||
| 915 |
function test_settle_failsIfLocked() public {
|
||
| 916 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 917 |
manager.settle(); |
||
| 918 |
} |
||
| 919 | |||
| 920 |
function test_settle_revertsSendingNativeWithToken() public noIsolate {
|
||
| 921 |
manager.sync(key.currency0); |
||
| 922 |
vm.expectRevert(IPoolManager.NonZeroNativeValue.selector); |
||
| 923 |
settleRouter.settle{value: 1}();
|
||
| 924 |
} |
||
| 925 | |||
| 926 |
function test_mint_failsIfLocked() public {
|
||
| 927 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 928 |
manager.mint(address(this), key.currency0.toId(), 1); |
||
| 929 |
} |
||
| 930 | |||
| 931 |
function test_burn_failsIfLocked() public {
|
||
| 932 |
vm.expectRevert(IPoolManager.ManagerLocked.selector); |
||
| 933 |
manager.burn(address(this), key.currency0.toId(), 1); |
||
| 934 |
} |
||
| 935 | |||
| 936 |
function test_collectProtocolFees_ERC20_accumulateFees_gas() public {
|
||
| 937 |
uint256 expectedFees = 10; |
||
| 938 | |||
| 939 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 940 |
assertEq(slot0ProtocolFee, 0); |
||
| 941 | |||
| 942 |
vm.prank(address(feeController)); |
||
| 943 |
manager.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 944 | |||
| 945 |
(,, slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 946 |
assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 947 | |||
| 948 |
swapRouter.swap( |
||
| 949 |
key, |
||
| 950 |
IPoolManager.SwapParams(true, -10000, SQRT_PRICE_1_2), |
||
| 951 |
PoolSwapTest.TestSettings(false, false), |
||
| 952 |
ZERO_BYTES |
||
| 953 |
); |
||
| 954 | |||
| 955 |
assertEq(manager.protocolFeesAccrued(currency0), expectedFees); |
||
| 956 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 957 |
assertEq(currency0.balanceOf(address(1)), 0); |
||
| 958 |
vm.prank(address(feeController)); |
||
| 959 |
manager.collectProtocolFees(address(1), currency0, expectedFees); |
||
| 960 |
snapLastCall("erc20 collect protocol fees");
|
||
| 961 |
assertEq(currency0.balanceOf(address(1)), expectedFees); |
||
| 962 |
assertEq(manager.protocolFeesAccrued(currency0), 0); |
||
| 963 |
} |
||
| 964 | |||
| 965 |
function test_collectProtocolFees_ERC20_accumulateFees_exactOutput() public {
|
||
| 966 |
uint256 expectedFees = 10; |
||
| 967 | |||
| 968 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 969 |
assertEq(slot0ProtocolFee, 0); |
||
| 970 | |||
| 971 |
vm.prank(address(feeController)); |
||
| 972 |
manager.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 973 | |||
| 974 |
(,, slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 975 |
assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 976 | |||
| 977 |
swapRouter.swap( |
||
| 978 |
key, |
||
| 979 |
IPoolManager.SwapParams(true, 10000, SQRT_PRICE_1_2), |
||
| 980 |
PoolSwapTest.TestSettings(false, false), |
||
| 981 |
ZERO_BYTES |
||
| 982 |
); |
||
| 983 | |||
| 984 |
assertEq(manager.protocolFeesAccrued(currency0), expectedFees); |
||
| 985 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 986 |
assertEq(currency0.balanceOf(address(1)), 0); |
||
| 987 |
vm.prank(address(feeController)); |
||
| 988 |
manager.collectProtocolFees(address(1), currency0, expectedFees); |
||
| 989 |
assertEq(currency0.balanceOf(address(1)), expectedFees); |
||
| 990 |
assertEq(manager.protocolFeesAccrued(currency0), 0); |
||
| 991 |
} |
||
| 992 | |||
| 993 |
function test_collectProtocolFees_ERC20_returnsAllFeesIf0IsProvidedAsParameter() public {
|
||
| 994 |
uint256 expectedFees = 10; |
||
| 995 | |||
| 996 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 997 |
assertEq(slot0ProtocolFee, 0); |
||
| 998 | |||
| 999 |
vm.prank(address(feeController)); |
||
| 1000 |
manager.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 1001 | |||
| 1002 |
(,, slot0ProtocolFee,) = manager.getSlot0(key.toId()); |
||
| 1003 |
assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 1004 | |||
| 1005 |
swapRouter.swap( |
||
| 1006 |
key, |
||
| 1007 |
IPoolManager.SwapParams(false, -10000, TickMath.MAX_SQRT_PRICE - 1), |
||
| 1008 |
PoolSwapTest.TestSettings(false, false), |
||
| 1009 |
ZERO_BYTES |
||
| 1010 |
); |
||
| 1011 | |||
| 1012 |
assertEq(manager.protocolFeesAccrued(currency0), 0); |
||
| 1013 |
assertEq(manager.protocolFeesAccrued(currency1), expectedFees); |
||
| 1014 |
assertEq(currency1.balanceOf(address(1)), 0); |
||
| 1015 |
vm.prank(address(feeController)); |
||
| 1016 |
manager.collectProtocolFees(address(1), currency1, 0); |
||
| 1017 |
assertEq(currency1.balanceOf(address(1)), expectedFees); |
||
| 1018 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 1019 |
} |
||
| 1020 | |||
| 1021 |
function test_collectProtocolFees_nativeToken_accumulateFees_gas() public {
|
||
| 1022 |
uint256 expectedFees = 10; |
||
| 1023 |
Currency nativeCurrency = CurrencyLibrary.NATIVE; |
||
| 1024 | |||
| 1025 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId()); |
||
| 1026 |
assertEq(slot0ProtocolFee, 0); |
||
| 1027 | |||
| 1028 |
vm.prank(address(feeController)); |
||
| 1029 |
manager.setProtocolFee(nativeKey, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 1030 | |||
| 1031 |
(,, slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId()); |
||
| 1032 |
assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 1033 | |||
| 1034 |
swapRouter.swap{value: 10000}(
|
||
| 1035 |
nativeKey, |
||
| 1036 |
IPoolManager.SwapParams(true, -10000, SQRT_PRICE_1_2), |
||
| 1037 |
PoolSwapTest.TestSettings(false, false), |
||
| 1038 |
ZERO_BYTES |
||
| 1039 |
); |
||
| 1040 | |||
| 1041 |
assertEq(manager.protocolFeesAccrued(nativeCurrency), expectedFees); |
||
| 1042 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 1043 |
assertEq(nativeCurrency.balanceOf(address(1)), 0); |
||
| 1044 |
vm.prank(address(feeController)); |
||
| 1045 |
manager.collectProtocolFees(address(1), nativeCurrency, expectedFees); |
||
| 1046 |
snapLastCall("native collect protocol fees");
|
||
| 1047 |
assertEq(nativeCurrency.balanceOf(address(1)), expectedFees); |
||
| 1048 |
assertEq(manager.protocolFeesAccrued(nativeCurrency), 0); |
||
| 1049 |
} |
||
| 1050 | |||
| 1051 |
function test_collectProtocolFees_nativeToken_returnsAllFeesIf0IsProvidedAsParameter() public {
|
||
| 1052 |
uint256 expectedFees = 10; |
||
| 1053 |
Currency nativeCurrency = CurrencyLibrary.NATIVE; |
||
| 1054 | |||
| 1055 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId()); |
||
| 1056 |
assertEq(slot0ProtocolFee, 0); |
||
| 1057 | |||
| 1058 |
vm.prank(address(feeController)); |
||
| 1059 |
manager.setProtocolFee(nativeKey, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 1060 | |||
| 1061 |
(,, slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId()); |
||
| 1062 |
assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 1063 | |||
| 1064 |
swapRouter.swap{value: 10000}(
|
||
| 1065 |
nativeKey, |
||
| 1066 |
IPoolManager.SwapParams(true, -10000, SQRT_PRICE_1_2), |
||
| 1067 |
PoolSwapTest.TestSettings(false, false), |
||
| 1068 |
ZERO_BYTES |
||
| 1069 |
); |
||
| 1070 | |||
| 1071 |
assertEq(manager.protocolFeesAccrued(nativeCurrency), expectedFees); |
||
| 1072 |
assertEq(manager.protocolFeesAccrued(currency1), 0); |
||
| 1073 |
assertEq(nativeCurrency.balanceOf(address(1)), 0); |
||
| 1074 |
vm.prank(address(feeController)); |
||
| 1075 |
manager.collectProtocolFees(address(1), nativeCurrency, 0); |
||
| 1076 |
assertEq(nativeCurrency.balanceOf(address(1)), expectedFees); |
||
| 1077 |
assertEq(manager.protocolFeesAccrued(nativeCurrency), 0); |
||
| 1078 |
} |
||
| 1079 | |||
| 1080 |
function test_unlock_EmitsCorrectId() public {
|
||
| 1081 |
vm.expectEmit(false, false, false, true); |
||
| 1082 |
emit UnlockCallback(); |
||
| 1083 |
emptyUnlockRouter.unlock(); |
||
| 1084 |
} |
||
| 1085 | |||
| 1086 |
Action[] actions; |
||
| 1087 | |||
| 1088 |
function test_unlock_cannotBeCalledTwiceByCaller() public {
|
||
| 1089 |
actions = [Action.NESTED_SELF_UNLOCK]; |
||
| 1090 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 1091 |
} |
||
| 1092 | |||
| 1093 |
function test_unlock_cannotBeCalledTwiceByDifferentCallers() public {
|
||
| 1094 |
actions = [Action.NESTED_EXECUTOR_UNLOCK]; |
||
| 1095 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 1096 |
} |
||
| 1097 | |||
| 1098 |
// function testExtsloadForPoolPrice() public {
|
||
| 1099 |
// IPoolManager.key = IPoolManager.PoolKey({
|
||
| 1100 |
// currency0: currency0, |
||
| 1101 |
// currency1: currency1, |
||
| 1102 |
// fee: 100, |
||
| 1103 |
// hooks: IHooks(address(0)), |
||
| 1104 |
// tickSpacing: 10 |
||
| 1105 |
// }); |
||
| 1106 |
// manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 1107 | |||
| 1108 |
// PoolId poolId = key.toId(); |
||
| 1109 |
// bytes32 slot0Bytes = manager.extsload(keccak256(abi.encode(poolId, POOL_SLOT))); |
||
| 1110 |
// snapLastCall("poolExtsloadSlot0");
|
||
| 1111 | |||
| 1112 |
// uint160 sqrtPriceX96Extsload; |
||
| 1113 |
// assembly {
|
||
| 1114 |
// sqrtPriceX96Extsload := and(slot0Bytes, sub(shl(160, 1), 1)) |
||
| 1115 |
// } |
||
| 1116 |
// (uint160 sqrtPriceX96Slot0,,,,,) = manager.getSlot0(poolId); |
||
| 1117 | |||
| 1118 |
// // assert that extsload loads the correct storage slot which matches the true slot0 |
||
| 1119 |
// assertEq(sqrtPriceX96Extsload, sqrtPriceX96Slot0); |
||
| 1120 |
// } |
||
| 1121 | |||
| 1122 |
// function testExtsloadMultipleSlots() public {
|
||
| 1123 |
// IPoolManager.key = IPoolManager.PoolKey({
|
||
| 1124 |
// currency0: currency0, |
||
| 1125 |
// currency1: currency1, |
||
| 1126 |
// fee: 100, |
||
| 1127 |
// hooks: IHooks(address(0)), |
||
| 1128 |
// tickSpacing: 10 |
||
| 1129 |
// }); |
||
| 1130 |
// manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 1131 | |||
| 1132 |
// // populate feeGrowthGlobalX128 struct w/ modify + swap |
||
| 1133 |
// modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-120, 120, 5 ether, 0)); |
||
| 1134 |
// swapRouter.swap( |
||
| 1135 |
// key, |
||
| 1136 |
// IPoolManager.SwapParams(false, 1 ether, TickMath.MAX_SQRT_PRICE - 1), |
||
| 1137 |
// PoolSwapTest.TestSettings(true, true) |
||
| 1138 |
// ); |
||
| 1139 |
// swapRouter.swap( |
||
| 1140 |
// key, |
||
| 1141 |
// IPoolManager.SwapParams(true, 5 ether, TickMath.MIN_SQRT_PRICE + 1), |
||
| 1142 |
// PoolSwapTest.TestSettings(true, true) |
||
| 1143 |
// ); |
||
| 1144 | |||
| 1145 |
// PoolId poolId = key.toId(); |
||
| 1146 |
// bytes memory value = manager.extsload(bytes32(uint256(keccak256(abi.encode(poolId, POOL_SLOT))) + 1), 2); |
||
| 1147 |
// snapLastCall("poolExtsloadTickInfoStruct");
|
||
| 1148 | |||
| 1149 |
// uint256 feeGrowthGlobal0X128Extsload; |
||
| 1150 |
// uint256 feeGrowthGlobal1X128Extsload; |
||
| 1151 |
// assembly {
|
||
| 1152 |
// feeGrowthGlobal0X128Extsload := and(mload(add(value, 0x20)), sub(shl(256, 1), 1)) |
||
| 1153 |
// feeGrowthGlobal1X128Extsload := and(mload(add(value, 0x40)), sub(shl(256, 1), 1)) |
||
| 1154 |
// } |
||
| 1155 | |||
| 1156 |
// assertEq(feeGrowthGlobal0X128Extsload, 408361710565269213475534193967158); |
||
| 1157 |
// assertEq(feeGrowthGlobal1X128Extsload, 204793365386061595215803889394593); |
||
| 1158 |
// } |
||
| 1159 | |||
| 1160 |
function test_getPosition() public view {
|
||
| 1161 |
Position.Info memory managerPosition = |
||
| 1162 |
manager.getPosition(key.toId(), address(modifyLiquidityRouter), -120, 120, 0); |
||
| 1163 |
assert(LIQUIDITY_PARAMS.liquidityDelta > 0); |
||
| 1164 |
assertEq(managerPosition.liquidity, uint128(uint256(LIQUIDITY_PARAMS.liquidityDelta))); |
||
| 1165 |
} |
||
| 1166 | |||
| 1167 |
function supportsInterface(bytes4) external pure returns (bool) {
|
||
| 1168 |
return true; |
||
| 1169 |
} |
||
| 1170 |
} |
||
| 1171 |
| Lines covered: | 0 / 154 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 6 |
import {Hooks} from "../src/libraries/Hooks.sol";
|
||
| 7 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 8 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 9 |
import {PoolManager} from "../src/PoolManager.sol";
|
||
| 10 |
import {TickMath} from "../src/libraries/TickMath.sol";
|
||
| 11 |
import {Pool} from "../src/libraries/Pool.sol";
|
||
| 12 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 13 |
import {Constants} from "./utils/Constants.sol";
|
||
| 14 |
import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
|
||
| 15 |
import {MockHooks} from "../src/test/MockHooks.sol";
|
||
| 16 |
import {MockContract} from "../src/test/MockContract.sol";
|
||
| 17 |
import {EmptyTestHooks} from "../src/test/EmptyTestHooks.sol";
|
||
| 18 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 19 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 20 |
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
|
||
| 21 |
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
|
||
| 22 |
import {ProtocolFeeControllerTest} from "../src/test/ProtocolFeeControllerTest.sol";
|
||
| 23 |
import {IProtocolFeeController} from "../src/interfaces/IProtocolFeeController.sol";
|
||
| 24 |
import {ProtocolFeeLibrary} from "../src/libraries/ProtocolFeeLibrary.sol";
|
||
| 25 |
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
|
||
| 26 | |||
| 27 |
contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
|
||
| 28 |
using Hooks for IHooks; |
||
| 29 |
using PoolIdLibrary for PoolKey; |
||
| 30 |
using LPFeeLibrary for uint24; |
||
| 31 |
using ProtocolFeeLibrary for uint24; |
||
| 32 |
using StateLibrary for IPoolManager; |
||
| 33 | |||
| 34 |
event Initialize( |
||
| 35 |
PoolId indexed poolId, |
||
| 36 |
Currency indexed currency0, |
||
| 37 |
Currency indexed currency1, |
||
| 38 |
uint24 fee, |
||
| 39 |
int24 tickSpacing, |
||
| 40 |
IHooks hooks |
||
| 41 |
); |
||
| 42 | |||
| 43 |
function setUp() public {
|
||
| 44 |
deployFreshManagerAndRouters(); |
||
| 45 |
deployMintAndApprove2Currencies(); |
||
| 46 | |||
| 47 |
uninitializedKey = PoolKey({
|
||
| 48 |
currency0: currency0, |
||
| 49 |
currency1: currency1, |
||
| 50 |
fee: 3000, |
||
| 51 |
hooks: IHooks(Constants.ADDRESS_ZERO), |
||
| 52 |
tickSpacing: 60 |
||
| 53 |
}); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function test_fuzz_initialize(PoolKey memory key0, uint160 sqrtPriceX96) public {
|
||
| 57 |
// Assumptions tested in Pool.t.sol |
||
| 58 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 59 | |||
| 60 |
// tested in Hooks.t.sol |
||
| 61 |
key0.hooks = IHooks(Constants.ADDRESS_ZERO); |
||
| 62 | |||
| 63 |
if (key0.tickSpacing > manager.MAX_TICK_SPACING()) {
|
||
| 64 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooLarge.selector, key0.tickSpacing)); |
||
| 65 |
manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); |
||
| 66 |
} else if (key0.tickSpacing < manager.MIN_TICK_SPACING()) {
|
||
| 67 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, key0.tickSpacing)); |
||
| 68 |
manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); |
||
| 69 |
} else if (key0.currency0 >= key0.currency1) {
|
||
| 70 |
vm.expectRevert( |
||
| 71 |
abi.encodeWithSelector( |
||
| 72 |
IPoolManager.CurrenciesOutOfOrderOrEqual.selector, key0.currency0, key0.currency1 |
||
| 73 |
) |
||
| 74 |
); |
||
| 75 |
manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); |
||
| 76 |
} else if (!key0.hooks.isValidHookAddress(key0.fee)) {
|
||
| 77 |
vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, address(key0.hooks))); |
||
| 78 |
manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); |
||
| 79 |
} else if ((key0.fee != LPFeeLibrary.DYNAMIC_FEE_FLAG) && (key0.fee > 1000000)) {
|
||
| 80 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, key0.fee)); |
||
| 81 |
manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); |
||
| 82 |
} else {
|
||
| 83 |
vm.expectEmit(true, true, true, true); |
||
| 84 |
emit Initialize(key0.toId(), key0.currency0, key0.currency1, key0.fee, key0.tickSpacing, key0.hooks); |
||
| 85 |
manager.initialize(key0, sqrtPriceX96, ZERO_BYTES); |
||
| 86 | |||
| 87 |
(uint160 slot0SqrtPriceX96,, uint24 slot0ProtocolFee,) = manager.getSlot0(key0.toId()); |
||
| 88 |
assertEq(slot0SqrtPriceX96, sqrtPriceX96); |
||
| 89 |
assertEq(slot0ProtocolFee, 0); |
||
| 90 |
} |
||
| 91 |
} |
||
| 92 | |||
| 93 |
function test_initialize_forNativeTokens(uint160 sqrtPriceX96) public {
|
||
| 94 |
// Assumptions tested in Pool.t.sol |
||
| 95 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 96 |
uninitializedKey.currency0 = CurrencyLibrary.NATIVE; |
||
| 97 | |||
| 98 |
vm.expectEmit(true, true, true, true); |
||
| 99 |
emit Initialize( |
||
| 100 |
uninitializedKey.toId(), |
||
| 101 |
uninitializedKey.currency0, |
||
| 102 |
uninitializedKey.currency1, |
||
| 103 |
uninitializedKey.fee, |
||
| 104 |
uninitializedKey.tickSpacing, |
||
| 105 |
uninitializedKey.hooks |
||
| 106 |
); |
||
| 107 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 108 | |||
| 109 |
(uint160 slot0SqrtPriceX96, int24 slot0Tick, uint24 slot0ProtocolFee,) = |
||
| 110 |
manager.getSlot0(uninitializedKey.toId()); |
||
| 111 |
assertEq(slot0SqrtPriceX96, sqrtPriceX96); |
||
| 112 |
assertEq(slot0ProtocolFee, 0); |
||
| 113 |
assertEq(slot0Tick, TickMath.getTickAtSqrtPrice(sqrtPriceX96)); |
||
| 114 |
} |
||
| 115 | |||
| 116 |
function test_initialize_succeedsWithHooks(uint160 sqrtPriceX96) public {
|
||
| 117 |
// Assumptions tested in Pool.t.sol |
||
| 118 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 119 | |||
| 120 |
address payable mockAddr = payable(address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG))); |
||
| 121 |
address payable hookAddr = payable(Constants.ALL_HOOKS); |
||
| 122 | |||
| 123 |
vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
|
||
| 124 |
MockContract mockContract = new MockContract(); |
||
| 125 |
vm.etch(mockAddr, address(mockContract).code); |
||
| 126 | |||
| 127 |
MockContract(mockAddr).setImplementation(hookAddr); |
||
| 128 | |||
| 129 |
uninitializedKey.hooks = IHooks(mockAddr); |
||
| 130 | |||
| 131 |
int24 tick = manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 132 |
(uint160 slot0SqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 133 |
assertEq(slot0SqrtPriceX96, sqrtPriceX96, "sqrtPrice"); |
||
| 134 | |||
| 135 |
bytes32 beforeSelector = MockHooks.beforeInitialize.selector; |
||
| 136 |
bytes memory beforeParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 137 | |||
| 138 |
bytes32 afterSelector = MockHooks.afterInitialize.selector; |
||
| 139 |
bytes memory afterParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, tick, ZERO_BYTES); |
||
| 140 | |||
| 141 |
assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1, "beforeSelector count"); |
||
| 142 |
assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams), "beforeSelector params"); |
||
| 143 |
assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1, "afterSelector count"); |
||
| 144 |
assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams), "afterSelector params"); |
||
| 145 |
} |
||
| 146 | |||
| 147 |
function test_initialize_succeedsWithMaxTickSpacing(uint160 sqrtPriceX96) public {
|
||
| 148 |
// Assumptions tested in Pool.t.sol |
||
| 149 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 150 | |||
| 151 |
uninitializedKey.tickSpacing = manager.MAX_TICK_SPACING(); |
||
| 152 | |||
| 153 |
vm.expectEmit(true, true, true, true); |
||
| 154 |
emit Initialize( |
||
| 155 |
uninitializedKey.toId(), |
||
| 156 |
uninitializedKey.currency0, |
||
| 157 |
uninitializedKey.currency1, |
||
| 158 |
uninitializedKey.fee, |
||
| 159 |
uninitializedKey.tickSpacing, |
||
| 160 |
uninitializedKey.hooks |
||
| 161 |
); |
||
| 162 | |||
| 163 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 164 |
} |
||
| 165 | |||
| 166 |
function test_initialize_succeedsWithEmptyHooks(uint160 sqrtPriceX96) public {
|
||
| 167 |
// Assumptions tested in Pool.t.sol |
||
| 168 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 169 | |||
| 170 |
address allHooksAddr = Constants.ALL_HOOKS; |
||
| 171 | |||
| 172 |
MockHooks impl = new MockHooks(); |
||
| 173 |
vm.etch(allHooksAddr, address(impl).code); |
||
| 174 |
MockHooks mockHooks = MockHooks(allHooksAddr); |
||
| 175 | |||
| 176 |
uninitializedKey.hooks = mockHooks; |
||
| 177 | |||
| 178 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 179 |
(uint160 slot0SqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 180 |
assertEq(slot0SqrtPriceX96, sqrtPriceX96); |
||
| 181 |
} |
||
| 182 | |||
| 183 |
function test_initialize_revertsWithIdenticalTokens(uint160 sqrtPriceX96) public {
|
||
| 184 |
// Assumptions tested in Pool.t.sol |
||
| 185 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 186 | |||
| 187 |
// Both currencies are currency0 |
||
| 188 |
uninitializedKey.currency1 = currency0; |
||
| 189 | |||
| 190 |
vm.expectRevert( |
||
| 191 |
abi.encodeWithSelector( |
||
| 192 |
IPoolManager.CurrenciesOutOfOrderOrEqual.selector, |
||
| 193 |
Currency.unwrap(currency0), |
||
| 194 |
Currency.unwrap(currency0) |
||
| 195 |
) |
||
| 196 |
); |
||
| 197 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 198 |
} |
||
| 199 | |||
| 200 |
function test_initialize_revertsWithSameTokenCombo(uint160 sqrtPriceX96) public {
|
||
| 201 |
// Assumptions tested in Pool.t.sol |
||
| 202 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 203 | |||
| 204 |
uninitializedKey.currency1 = currency0; |
||
| 205 |
uninitializedKey.currency0 = currency1; |
||
| 206 | |||
| 207 |
vm.expectRevert( |
||
| 208 |
abi.encodeWithSelector( |
||
| 209 |
IPoolManager.CurrenciesOutOfOrderOrEqual.selector, |
||
| 210 |
Currency.unwrap(currency1), |
||
| 211 |
Currency.unwrap(currency0) |
||
| 212 |
) |
||
| 213 |
); |
||
| 214 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 215 |
} |
||
| 216 | |||
| 217 |
function test_initialize_fetchFeeWhenController(uint24 protocolFee) public {
|
||
| 218 |
manager.setProtocolFeeController(feeController); |
||
| 219 |
feeController.setProtocolFeeForPool(uninitializedKey.toId(), protocolFee); |
||
| 220 | |||
| 221 |
uint16 fee0 = protocolFee.getZeroForOneFee(); |
||
| 222 |
uint16 fee1 = protocolFee.getOneForZeroFee(); |
||
| 223 | |||
| 224 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 225 | |||
| 226 |
(uint160 slot0SqrtPriceX96,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 227 |
assertEq(slot0SqrtPriceX96, SQRT_PRICE_1_1); |
||
| 228 |
if ((fee0 > 1000) || (fee1 > 1000)) {
|
||
| 229 |
assertEq(slot0ProtocolFee, 0); |
||
| 230 |
} else {
|
||
| 231 |
assertEq(slot0ProtocolFee, protocolFee); |
||
| 232 |
} |
||
| 233 |
} |
||
| 234 | |||
| 235 |
function test_initialize_revertsWhenPoolAlreadyInitialized(uint160 sqrtPriceX96) public {
|
||
| 236 |
// Assumptions tested in Pool.t.sol |
||
| 237 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 238 | |||
| 239 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 240 |
vm.expectRevert(Pool.PoolAlreadyInitialized.selector); |
||
| 241 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 242 |
} |
||
| 243 | |||
| 244 |
function test_initialize_failsWithIncorrectSelectors() public {
|
||
| 245 |
address hookAddr = address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 246 | |||
| 247 |
MockHooks impl = new MockHooks(); |
||
| 248 |
vm.etch(hookAddr, address(impl).code); |
||
| 249 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 250 | |||
| 251 |
uninitializedKey.hooks = mockHooks; |
||
| 252 | |||
| 253 |
mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, bytes4(0xdeadbeef)); |
||
| 254 |
mockHooks.setReturnValue(mockHooks.afterInitialize.selector, bytes4(0xdeadbeef)); |
||
| 255 | |||
| 256 |
// Fails at beforeInitialize hook. |
||
| 257 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 258 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 259 | |||
| 260 |
// Fail at afterInitialize hook. |
||
| 261 |
mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, mockHooks.beforeInitialize.selector); |
||
| 262 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 263 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 264 |
} |
||
| 265 | |||
| 266 |
function test_initialize_succeedsWithCorrectSelectors() public {
|
||
| 267 |
address hookAddr = address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 268 | |||
| 269 |
MockHooks impl = new MockHooks(); |
||
| 270 |
vm.etch(hookAddr, address(impl).code); |
||
| 271 |
MockHooks mockHooks = MockHooks(hookAddr); |
||
| 272 | |||
| 273 |
uninitializedKey.hooks = mockHooks; |
||
| 274 | |||
| 275 |
mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, mockHooks.beforeInitialize.selector); |
||
| 276 |
mockHooks.setReturnValue(mockHooks.afterInitialize.selector, mockHooks.afterInitialize.selector); |
||
| 277 | |||
| 278 |
vm.expectEmit(true, true, true, true); |
||
| 279 |
emit Initialize( |
||
| 280 |
uninitializedKey.toId(), |
||
| 281 |
uninitializedKey.currency0, |
||
| 282 |
uninitializedKey.currency1, |
||
| 283 |
uninitializedKey.fee, |
||
| 284 |
uninitializedKey.tickSpacing, |
||
| 285 |
uninitializedKey.hooks |
||
| 286 |
); |
||
| 287 | |||
| 288 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 289 |
} |
||
| 290 | |||
| 291 |
function test_initialize_failsIfTickSpaceTooLarge(uint160 sqrtPriceX96) public {
|
||
| 292 |
// Assumptions tested in Pool.t.sol |
||
| 293 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 294 | |||
| 295 |
uninitializedKey.tickSpacing = manager.MAX_TICK_SPACING() + 1; |
||
| 296 | |||
| 297 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooLarge.selector, uninitializedKey.tickSpacing)); |
||
| 298 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 299 |
} |
||
| 300 | |||
| 301 |
function test_initialize_failsIfTickSpaceZero(uint160 sqrtPriceX96) public {
|
||
| 302 |
// Assumptions tested in Pool.t.sol |
||
| 303 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 304 | |||
| 305 |
uninitializedKey.tickSpacing = 0; |
||
| 306 | |||
| 307 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, uninitializedKey.tickSpacing)); |
||
| 308 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 309 |
} |
||
| 310 | |||
| 311 |
function test_initialize_failsIfTickSpaceNeg(uint160 sqrtPriceX96) public {
|
||
| 312 |
// Assumptions tested in Pool.t.sol |
||
| 313 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 314 | |||
| 315 |
uninitializedKey.tickSpacing = -1; |
||
| 316 | |||
| 317 |
vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, uninitializedKey.tickSpacing)); |
||
| 318 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 319 |
} |
||
| 320 | |||
| 321 |
function test_initialize_succeedsWithOutOfBoundsFeeController(uint160 sqrtPriceX96) public {
|
||
| 322 |
// Assumptions tested in Pool.t.sol |
||
| 323 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 324 | |||
| 325 |
manager.setProtocolFeeController(outOfBoundsFeeController); |
||
| 326 |
// expect initialize to succeed even though the controller reverts |
||
| 327 |
vm.expectEmit(true, true, true, true); |
||
| 328 |
emit Initialize( |
||
| 329 |
uninitializedKey.toId(), |
||
| 330 |
uninitializedKey.currency0, |
||
| 331 |
uninitializedKey.currency1, |
||
| 332 |
uninitializedKey.fee, |
||
| 333 |
uninitializedKey.tickSpacing, |
||
| 334 |
uninitializedKey.hooks |
||
| 335 |
); |
||
| 336 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 337 |
// protocol fees should default to 0 |
||
| 338 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 339 |
assertEq(slot0ProtocolFee, 0); |
||
| 340 |
} |
||
| 341 | |||
| 342 |
function test_initialize_succeedsWithRevertingFeeController(uint160 sqrtPriceX96) public {
|
||
| 343 |
// Assumptions tested in Pool.t.sol |
||
| 344 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 345 | |||
| 346 |
manager.setProtocolFeeController(revertingFeeController); |
||
| 347 |
// expect initialize to succeed even though the controller reverts |
||
| 348 |
vm.expectEmit(true, true, true, true); |
||
| 349 |
emit Initialize( |
||
| 350 |
uninitializedKey.toId(), |
||
| 351 |
uninitializedKey.currency0, |
||
| 352 |
uninitializedKey.currency1, |
||
| 353 |
uninitializedKey.fee, |
||
| 354 |
uninitializedKey.tickSpacing, |
||
| 355 |
uninitializedKey.hooks |
||
| 356 |
); |
||
| 357 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 358 |
// protocol fees should default to 0 |
||
| 359 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 360 |
assertEq(slot0ProtocolFee, 0); |
||
| 361 |
} |
||
| 362 | |||
| 363 |
function test_initialize_succeedsWithOverflowFeeController(uint160 sqrtPriceX96) public {
|
||
| 364 |
// Assumptions tested in Pool.t.sol |
||
| 365 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 366 | |||
| 367 |
manager.setProtocolFeeController(overflowFeeController); |
||
| 368 |
// expect initialize to succeed |
||
| 369 |
vm.expectEmit(true, true, true, true); |
||
| 370 |
emit Initialize( |
||
| 371 |
uninitializedKey.toId(), |
||
| 372 |
uninitializedKey.currency0, |
||
| 373 |
uninitializedKey.currency1, |
||
| 374 |
uninitializedKey.fee, |
||
| 375 |
uninitializedKey.tickSpacing, |
||
| 376 |
uninitializedKey.hooks |
||
| 377 |
); |
||
| 378 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 379 |
// protocol fees should default to 0 |
||
| 380 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 381 |
assertEq(slot0ProtocolFee, 0); |
||
| 382 |
} |
||
| 383 | |||
| 384 |
function test_initialize_succeedsWithWrongReturnSizeFeeController(uint160 sqrtPriceX96) public {
|
||
| 385 |
// Assumptions tested in Pool.t.sol |
||
| 386 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1)); |
||
| 387 | |||
| 388 |
manager.setProtocolFeeController(invalidReturnSizeFeeController); |
||
| 389 |
// expect initialize to succeed |
||
| 390 |
vm.expectEmit(true, true, true, true); |
||
| 391 |
emit Initialize( |
||
| 392 |
uninitializedKey.toId(), |
||
| 393 |
uninitializedKey.currency0, |
||
| 394 |
uninitializedKey.currency1, |
||
| 395 |
uninitializedKey.fee, |
||
| 396 |
uninitializedKey.tickSpacing, |
||
| 397 |
uninitializedKey.hooks |
||
| 398 |
); |
||
| 399 |
manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES); |
||
| 400 |
// protocol fees should default to 0 |
||
| 401 |
(,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 402 |
assertEq(slot0ProtocolFee, 0); |
||
| 403 |
} |
||
| 404 | |||
| 405 |
function test_initialize_gas() public {
|
||
| 406 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 407 |
snapLastCall("initialize");
|
||
| 408 |
} |
||
| 409 |
} |
||
| 410 |
| Lines covered: | 0 / 103 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.15; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 6 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 7 |
import {ProtocolFeesImplementation} from "../src/test/ProtocolFeesImplementation.sol";
|
||
| 8 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 9 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 10 |
import {ProtocolFeeLibrary} from "../src/libraries/ProtocolFeeLibrary.sol";
|
||
| 11 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 12 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 13 |
import {Deployers} from "../test/utils/Deployers.sol";
|
||
| 14 |
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
|
||
| 15 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 16 |
import {Constants} from "../test/utils/Constants.sol";
|
||
| 17 |
import {
|
||
| 18 |
ProtocolFeeControllerTest, |
||
| 19 |
OutOfBoundsProtocolFeeControllerTest, |
||
| 20 |
RevertingProtocolFeeControllerTest, |
||
| 21 |
OverflowProtocolFeeControllerTest, |
||
| 22 |
InvalidReturnSizeProtocolFeeControllerTest |
||
| 23 |
} from "../src/test/ProtocolFeeControllerTest.sol"; |
||
| 24 | |||
| 25 |
contract ProtocolFeesTest is Test, GasSnapshot, Deployers {
|
||
| 26 |
using PoolIdLibrary for PoolKey; |
||
| 27 |
using ProtocolFeeLibrary for uint24; |
||
| 28 | |||
| 29 |
event ProtocolFeeControllerUpdated(address indexed feeController); |
||
| 30 |
event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee); |
||
| 31 | |||
| 32 |
uint24 constant MAX_PROTOCOL_FEE_BOTH_TOKENS = (1000 << 12) | 1000; // 1000 1000 |
||
| 33 | |||
| 34 |
ProtocolFeesImplementation protocolFees; |
||
| 35 | |||
| 36 |
function setUp() public {
|
||
| 37 |
protocolFees = new ProtocolFeesImplementation(5000); |
||
| 38 |
feeController = new ProtocolFeeControllerTest(); |
||
| 39 |
(currency0, currency1) = deployAndMint2Currencies(); |
||
| 40 |
MockERC20(Currency.unwrap(currency0)).transfer(address(protocolFees), 2 ** 255); |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_setProtocolFeeController_succeedsNoRevert() public {
|
||
| 44 |
assertEq(address(protocolFees.protocolFeeController()), address(0)); |
||
| 45 |
vm.expectEmit(true, false, false, false, address(protocolFees)); |
||
| 46 |
emit ProtocolFeeControllerUpdated(address(feeController)); |
||
| 47 |
protocolFees.setProtocolFeeController(feeController); |
||
| 48 |
assertEq(address(protocolFees.protocolFeeController()), address(feeController)); |
||
| 49 |
} |
||
| 50 | |||
| 51 |
function test_setProtocolFeeController_revertsWithNotAuthorized() public {
|
||
| 52 |
assertEq(address(protocolFees.protocolFeeController()), address(0)); |
||
| 53 | |||
| 54 |
vm.prank(address(1)); // not the owner address |
||
| 55 |
vm.expectRevert("UNAUTHORIZED");
|
||
| 56 |
protocolFees.setProtocolFeeController(feeController); |
||
| 57 |
assertEq(address(protocolFees.protocolFeeController()), address(0)); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function test_setProtocolFee_succeeds_gas() public {
|
||
| 61 |
PoolKey memory key = PoolKey(currency0, currency1, 3000, 60, IHooks(address(0))); |
||
| 62 |
protocolFees.setProtocolFeeController(feeController); |
||
| 63 |
// Set price to pretend that the pool is initialized |
||
| 64 |
protocolFees.setPrice(key, Constants.SQRT_PRICE_1_1); |
||
| 65 |
vm.prank(address(feeController)); |
||
| 66 |
vm.expectEmit(true, false, false, true, address(protocolFees)); |
||
| 67 |
emit ProtocolFeeUpdated(key.toId(), MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 68 |
protocolFees.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS); |
||
| 69 |
snapLastCall("set protocol fee");
|
||
| 70 |
} |
||
| 71 | |||
| 72 |
function test_setProtocolFee_revertsWithInvalidCaller() public {
|
||
| 73 |
protocolFees.setProtocolFeeController(feeController); |
||
| 74 |
vm.expectRevert(IProtocolFees.InvalidCaller.selector); |
||
| 75 |
protocolFees.setProtocolFee(key, 1); |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function test_setProtocolFee_revertsWithInvalidFee() public {
|
||
| 79 |
uint24 protocolFee = MAX_PROTOCOL_FEE_BOTH_TOKENS + 1; |
||
| 80 | |||
| 81 |
protocolFees.setProtocolFeeController(feeController); |
||
| 82 |
vm.prank(address(feeController)); |
||
| 83 |
vm.expectRevert(abi.encodeWithSelector(IProtocolFees.ProtocolFeeTooLarge.selector, protocolFee)); |
||
| 84 |
protocolFees.setProtocolFee(key, protocolFee); |
||
| 85 | |||
| 86 |
protocolFee = MAX_PROTOCOL_FEE_BOTH_TOKENS + (1 << 12); |
||
| 87 |
vm.prank(address(feeController)); |
||
| 88 |
vm.expectRevert(abi.encodeWithSelector(IProtocolFees.ProtocolFeeTooLarge.selector, protocolFee)); |
||
| 89 |
protocolFees.setProtocolFee(key, protocolFee); |
||
| 90 |
} |
||
| 91 | |||
| 92 |
function test_fuzz_setProtocolFee(PoolKey memory key, uint24 protocolFee) public {
|
||
| 93 |
protocolFees.setProtocolFeeController(feeController); |
||
| 94 |
// Set price to pretend that the pool is initialized |
||
| 95 |
protocolFees.setPrice(key, Constants.SQRT_PRICE_1_1); |
||
| 96 |
uint16 fee0 = protocolFee.getZeroForOneFee(); |
||
| 97 |
uint16 fee1 = protocolFee.getOneForZeroFee(); |
||
| 98 |
vm.prank(address(feeController)); |
||
| 99 |
if ((fee0 > 1000) || (fee1 > 1000)) {
|
||
| 100 |
vm.expectRevert(abi.encodeWithSelector(IProtocolFees.ProtocolFeeTooLarge.selector, protocolFee)); |
||
| 101 |
protocolFees.setProtocolFee(key, protocolFee); |
||
| 102 |
} else {
|
||
| 103 |
vm.expectEmit(true, false, false, true, address(protocolFees)); |
||
| 104 |
emit IProtocolFees.ProtocolFeeUpdated(key.toId(), protocolFee); |
||
| 105 |
protocolFees.setProtocolFee(key, protocolFee); |
||
| 106 |
} |
||
| 107 |
} |
||
| 108 | |||
| 109 |
function test_collectProtocolFees_revertsWithInvalidCaller() public {
|
||
| 110 |
vm.expectRevert(IProtocolFees.InvalidCaller.selector); |
||
| 111 |
protocolFees.collectProtocolFees(address(1), currency0, 0); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function test_collectProtocolFees_succeeds() public {
|
||
| 115 |
// set a balance of protocol fees that can be collected |
||
| 116 |
protocolFees.updateProtocolFees(currency0, 100); |
||
| 117 |
assertEq(protocolFees.protocolFeesAccrued(currency0), 100); |
||
| 118 | |||
| 119 |
protocolFees.setProtocolFeeController(feeController); |
||
| 120 |
vm.prank(address(feeController)); |
||
| 121 |
protocolFees.collectProtocolFees(address(this), currency0, 100); |
||
| 122 |
assertEq(protocolFees.protocolFeesAccrued(currency0), 0); |
||
| 123 |
assertEq(currency0.balanceOf(address(this)), 100); |
||
| 124 |
} |
||
| 125 | |||
| 126 |
function test_fuzz_collectProtocolFees(address recipient, uint256 amount, uint256 feesAccrued) public {
|
||
| 127 |
vm.assume(feesAccrued <= currency0.balanceOf(address(protocolFees))); |
||
| 128 | |||
| 129 |
uint256 recipientBalanceBefore = currency0.balanceOf(recipient); |
||
| 130 |
uint256 senderBalanceBefore = currency0.balanceOf(address(protocolFees)); |
||
| 131 | |||
| 132 |
// set a balance of protocol fees that can be collected |
||
| 133 |
protocolFees.updateProtocolFees(currency0, feesAccrued); |
||
| 134 |
assertEq(protocolFees.protocolFeesAccrued(currency0), feesAccrued); |
||
| 135 |
if (amount == 0) {
|
||
| 136 |
amount = protocolFees.protocolFeesAccrued(currency0); |
||
| 137 |
} |
||
| 138 | |||
| 139 |
protocolFees.setProtocolFeeController(feeController); |
||
| 140 |
vm.prank(address(feeController)); |
||
| 141 |
if (amount > feesAccrued) {
|
||
| 142 |
vm.expectRevert(); |
||
| 143 |
} |
||
| 144 |
uint256 amountCollected = protocolFees.collectProtocolFees(recipient, currency0, amount); |
||
| 145 | |||
| 146 |
if (amount <= feesAccrued) {
|
||
| 147 |
if (recipient == address(protocolFees)) {
|
||
| 148 |
assertEq(currency0.balanceOf(recipient), recipientBalanceBefore); |
||
| 149 |
} else {
|
||
| 150 |
assertEq(currency0.balanceOf(recipient), recipientBalanceBefore + amount); |
||
| 151 |
assertEq(currency0.balanceOf(address(protocolFees)), senderBalanceBefore - amount); |
||
| 152 |
} |
||
| 153 |
assertEq(protocolFees.protocolFeesAccrued(currency0), feesAccrued - amount); |
||
| 154 |
assertEq(amountCollected, amount); |
||
| 155 |
} |
||
| 156 |
} |
||
| 157 | |||
| 158 |
function test_updateProtocolFees_succeeds() public {
|
||
| 159 |
// set a starting balance of protocol fees |
||
| 160 |
protocolFees.updateProtocolFees(currency0, 100); |
||
| 161 |
assertEq(protocolFees.protocolFeesAccrued(currency0), 100); |
||
| 162 | |||
| 163 |
protocolFees.updateProtocolFees(currency0, 200); |
||
| 164 |
assertEq(protocolFees.protocolFeesAccrued(currency0), 300); |
||
| 165 |
} |
||
| 166 | |||
| 167 |
function test_fuzz_updateProtocolFees(uint256 amount, uint256 startingAmount) public {
|
||
| 168 |
// set a starting balance of protocol fees |
||
| 169 |
protocolFees.updateProtocolFees(currency0, startingAmount); |
||
| 170 |
assertEq(protocolFees.protocolFeesAccrued(currency0), startingAmount); |
||
| 171 | |||
| 172 |
uint256 newAmount; |
||
| 173 |
unchecked {
|
||
| 174 |
newAmount = startingAmount + amount; |
||
| 175 |
} |
||
| 176 | |||
| 177 |
protocolFees.updateProtocolFees(currency0, amount); |
||
| 178 |
assertEq(protocolFees.protocolFeesAccrued(currency0), newAmount); |
||
| 179 |
} |
||
| 180 | |||
| 181 |
function test_fetchProtocolFee_succeeds() public {
|
||
| 182 |
protocolFees.setProtocolFeeController(feeController); |
||
| 183 |
vm.prank(address(feeController)); |
||
| 184 |
(bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key); |
||
| 185 |
assertTrue(success); |
||
| 186 |
assertEq(protocolFee, 0); |
||
| 187 |
} |
||
| 188 | |||
| 189 |
function test_fetchProtocolFee_outOfBounds() public {
|
||
| 190 |
outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest(); |
||
| 191 |
protocolFees.setProtocolFeeController(outOfBoundsFeeController); |
||
| 192 |
vm.prank(address(outOfBoundsFeeController)); |
||
| 193 |
(bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key); |
||
| 194 |
assertFalse(success); |
||
| 195 |
assertEq(protocolFee, 0); |
||
| 196 |
} |
||
| 197 | |||
| 198 |
function test_fetchProtocolFee_overflowFee() public {
|
||
| 199 |
overflowFeeController = new OverflowProtocolFeeControllerTest(); |
||
| 200 |
protocolFees.setProtocolFeeController(overflowFeeController); |
||
| 201 |
vm.prank(address(overflowFeeController)); |
||
| 202 |
(bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key); |
||
| 203 |
assertFalse(success); |
||
| 204 |
assertEq(protocolFee, 0); |
||
| 205 |
} |
||
| 206 | |||
| 207 |
function test_fetchProtocolFee_invalidReturnSize() public {
|
||
| 208 |
invalidReturnSizeFeeController = new InvalidReturnSizeProtocolFeeControllerTest(); |
||
| 209 |
protocolFees.setProtocolFeeController(invalidReturnSizeFeeController); |
||
| 210 |
vm.prank(address(invalidReturnSizeFeeController)); |
||
| 211 |
(bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key); |
||
| 212 |
assertFalse(success); |
||
| 213 |
assertEq(protocolFee, 0); |
||
| 214 |
} |
||
| 215 | |||
| 216 |
function test_fetchProtocolFee_revert() public {
|
||
| 217 |
revertingFeeController = new RevertingProtocolFeeControllerTest(); |
||
| 218 |
protocolFees.setProtocolFeeController(revertingFeeController); |
||
| 219 |
vm.prank(address(revertingFeeController)); |
||
| 220 |
(bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key); |
||
| 221 |
assertFalse(success); |
||
| 222 |
assertEq(protocolFee, 0); |
||
| 223 |
} |
||
| 224 |
} |
||
| 225 |
| Lines covered: | 0 / 59 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
|
||
| 7 |
import {Hooks} from "../src/libraries/Hooks.sol";
|
||
| 8 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 9 |
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
|
||
| 10 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 11 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 12 |
import {PoolManager} from "../src/PoolManager.sol";
|
||
| 13 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 14 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 15 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 16 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 17 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 18 |
import {Constants} from "../test/utils/Constants.sol";
|
||
| 19 |
import {SkipCallsTestHook} from "../src/test/SkipCallsTestHook.sol";
|
||
| 20 | |||
| 21 |
contract SkipCallsTest is Test, Deployers, GasSnapshot {
|
||
| 22 |
using PoolIdLibrary for PoolKey; |
||
| 23 | |||
| 24 |
PoolSwapTest.TestSettings testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 25 | |||
| 26 |
function deploy(SkipCallsTestHook skipCallsTestHook) private {
|
||
| 27 |
SkipCallsTestHook impl = new SkipCallsTestHook(); |
||
| 28 |
vm.etch(address(skipCallsTestHook), address(impl).code); |
||
| 29 |
deployFreshManagerAndRouters(); |
||
| 30 |
skipCallsTestHook.setManager(IPoolManager(manager)); |
||
| 31 |
deployMintAndApprove2Currencies(); |
||
| 32 | |||
| 33 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 34 | |||
| 35 |
(key,) = initPool(currency0, currency1, IHooks(address(skipCallsTestHook)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function approveAndAddLiquidity(SkipCallsTestHook skipCallsTestHook) private {
|
||
| 39 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(skipCallsTestHook), Constants.MAX_UINT256); |
||
| 40 |
MockERC20(Currency.unwrap(key.currency1)).approve(address(skipCallsTestHook), Constants.MAX_UINT256); |
||
| 41 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function test_beforeInitialize_skipIfCalledByHook() public {
|
||
| 45 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 46 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_INITIALIZE_FLAG)) |
||
| 47 |
); |
||
| 48 | |||
| 49 |
// initializes pool and increments counter |
||
| 50 |
deploy(skipCallsTestHook); |
||
| 51 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
function test_afterInitialize_skipIfCalledByHook() public {
|
||
| 55 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 56 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_INITIALIZE_FLAG)) |
||
| 57 |
); |
||
| 58 | |||
| 59 |
// initializes pool and increments counter |
||
| 60 |
deploy(skipCallsTestHook); |
||
| 61 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function test_beforeAddLiquidity_skipIfCalledByHook() public {
|
||
| 65 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 66 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_ADD_LIQUIDITY_FLAG)) |
||
| 67 |
); |
||
| 68 | |||
| 69 |
deploy(skipCallsTestHook); |
||
| 70 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 71 | |||
| 72 |
// adds liquidity and increments counter |
||
| 73 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 74 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 75 |
// adds liquidity again and increments counter |
||
| 76 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 77 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
function test_afterAddLiquidity_skipIfCalledByHook() public {
|
||
| 81 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 82 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_ADD_LIQUIDITY_FLAG)) |
||
| 83 |
); |
||
| 84 | |||
| 85 |
deploy(skipCallsTestHook); |
||
| 86 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 87 | |||
| 88 |
// adds liquidity and increments counter |
||
| 89 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 90 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 91 |
// adds liquidity and increments counter again |
||
| 92 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 93 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
function test_beforeRemoveLiquidity_skipIfCalledByHook() public {
|
||
| 97 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 98 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)) |
||
| 99 |
); |
||
| 100 | |||
| 101 |
deploy(skipCallsTestHook); |
||
| 102 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 103 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 104 | |||
| 105 |
// removes liquidity and increments counter |
||
| 106 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 107 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 108 |
// adds liquidity again |
||
| 109 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 110 |
// removes liquidity again and increments counter |
||
| 111 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 112 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 113 |
} |
||
| 114 | |||
| 115 |
function test_afterRemoveLiquidity_skipIfCalledByHook() public {
|
||
| 116 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 117 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)) |
||
| 118 |
); |
||
| 119 | |||
| 120 |
deploy(skipCallsTestHook); |
||
| 121 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 122 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 123 | |||
| 124 |
// removes liquidity and increments counter |
||
| 125 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 126 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 127 |
// adds liquidity again |
||
| 128 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 129 |
// removes liquidity again and increments counter |
||
| 130 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this))); |
||
| 131 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 132 |
} |
||
| 133 | |||
| 134 |
function test_beforeSwap_skipIfCalledByHook() public {
|
||
| 135 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 136 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG)) |
||
| 137 |
); |
||
| 138 | |||
| 139 |
deploy(skipCallsTestHook); |
||
| 140 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 141 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 142 | |||
| 143 |
// swaps and increments counter |
||
| 144 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this))); |
||
| 145 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 146 |
// swaps again and increments counter |
||
| 147 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this))); |
||
| 148 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 149 |
} |
||
| 150 | |||
| 151 |
function test_gas_beforeSwap_skipIfCalledByHook() public {
|
||
| 152 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 153 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG)) |
||
| 154 |
); |
||
| 155 | |||
| 156 |
deploy(skipCallsTestHook); |
||
| 157 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 158 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 159 | |||
| 160 |
// swaps and increments counter |
||
| 161 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this))); |
||
| 162 |
snapLastCall("swap skips hook call if hook is caller");
|
||
| 163 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 164 |
} |
||
| 165 | |||
| 166 |
function test_afterSwap_skipIfCalledByHook() public {
|
||
| 167 |
SkipCallsTestHook skipCallsTestHook = |
||
| 168 |
SkipCallsTestHook(address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_SWAP_FLAG))); |
||
| 169 | |||
| 170 |
deploy(skipCallsTestHook); |
||
| 171 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 172 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 173 | |||
| 174 |
// swaps and increments counter |
||
| 175 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this))); |
||
| 176 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 177 |
// swaps again and increments counter |
||
| 178 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this))); |
||
| 179 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 180 |
} |
||
| 181 | |||
| 182 |
function test_beforeDonate_skipIfCalledByHook() public {
|
||
| 183 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 184 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_DONATE_FLAG)) |
||
| 185 |
); |
||
| 186 | |||
| 187 |
deploy(skipCallsTestHook); |
||
| 188 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 189 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 190 | |||
| 191 |
// donates and increments counter |
||
| 192 |
donateRouter.donate(key, 100, 200, abi.encode(address(this))); |
||
| 193 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 194 |
// donates again and increments counter |
||
| 195 |
donateRouter.donate(key, 100, 200, abi.encode(address(this))); |
||
| 196 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 197 |
} |
||
| 198 | |||
| 199 |
function test_afterDonate_skipIfCalledByHook() public {
|
||
| 200 |
SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook( |
||
| 201 |
address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_DONATE_FLAG)) |
||
| 202 |
); |
||
| 203 | |||
| 204 |
deploy(skipCallsTestHook); |
||
| 205 |
approveAndAddLiquidity(skipCallsTestHook); |
||
| 206 |
assertEq(skipCallsTestHook.counter(), 0); |
||
| 207 | |||
| 208 |
// donates and increments counter |
||
| 209 |
donateRouter.donate(key, 100, 200, abi.encode(address(this))); |
||
| 210 |
assertEq(skipCallsTestHook.counter(), 1); |
||
| 211 |
// donates again and increments counter |
||
| 212 |
donateRouter.donate(key, 100, 200, abi.encode(address(this))); |
||
| 213 |
assertEq(skipCallsTestHook.counter(), 2); |
||
| 214 |
} |
||
| 215 |
} |
||
| 216 |
| Lines covered: | 0 / 111 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 6 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 7 | |||
| 8 |
import {Deployers} from "./utils/Deployers.sol";
|
||
| 9 |
import {IHooks} from "../src/interfaces/IHooks.sol";
|
||
| 10 |
import {Currency} from "../src/types/Currency.sol";
|
||
| 11 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 12 |
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
|
||
| 13 |
import {IUnlockCallback} from "../src/interfaces/callback/IUnlockCallback.sol";
|
||
| 14 |
import {PoolKey} from "../src/types/PoolKey.sol";
|
||
| 15 |
import {ActionsRouter, Actions} from "../src/test/ActionsRouter.sol";
|
||
| 16 |
import {SafeCast} from "../src/libraries/SafeCast.sol";
|
||
| 17 |
import {CurrencyReserves} from "../src/libraries/CurrencyReserves.sol";
|
||
| 18 |
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
|
||
| 19 |
import {TransientStateLibrary} from "../src/libraries/TransientStateLibrary.sol";
|
||
| 20 |
import {NativeERC20} from "../src/test/NativeERC20.sol";
|
||
| 21 |
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
|
||
| 22 | |||
| 23 |
contract SyncTest is Test, Deployers, GasSnapshot {
|
||
| 24 |
using StateLibrary for IPoolManager; |
||
| 25 |
using TransientStateLibrary for IPoolManager; |
||
| 26 | |||
| 27 |
// PoolManager has no balance of currency2. |
||
| 28 |
Currency currency2; |
||
| 29 |
ActionsRouter router; |
||
| 30 | |||
| 31 |
function setUp() public {
|
||
| 32 |
initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0))); |
||
| 33 |
currency2 = deployMintAndApproveCurrency(); |
||
| 34 |
router = new ActionsRouter(manager); |
||
| 35 |
} |
||
| 36 | |||
| 37 |
function test_sync_balanceIsZero() public noIsolate {
|
||
| 38 |
assertEq(currency2.balanceOf(address(manager)), uint256(0)); |
||
| 39 |
manager.sync(currency2); |
||
| 40 |
uint256 balance = currency2.balanceOf(address(manager)); |
||
| 41 | |||
| 42 |
assertEq(uint256(balance), 0); |
||
| 43 |
assertEq(manager.getSyncedReserves(), 0); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function test_sync_balanceIsNonZero() public noIsolate {
|
||
| 47 |
uint256 currency0Balance = currency0.balanceOf(address(manager)); |
||
| 48 |
assertGt(currency0Balance, uint256(0)); |
||
| 49 | |||
| 50 |
// Without calling sync, getReserves should return 0. |
||
| 51 |
assertEq(manager.getSyncedReserves(), 0); |
||
| 52 | |||
| 53 |
manager.sync(currency0); |
||
| 54 |
uint256 balance = currency0.balanceOf(address(manager)); |
||
| 55 |
assertEq(balance, currency0Balance, "balance not equal"); |
||
| 56 |
assertEq(manager.getSyncedReserves(), balance); |
||
| 57 |
} |
||
| 58 | |||
| 59 |
function test_settle_withStartingBalance() public noIsolate {
|
||
| 60 |
assertGt(currency0.balanceOf(address(manager)), uint256(0)); |
||
| 61 | |||
| 62 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 63 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 64 | |||
| 65 |
// Sync has not been called. |
||
| 66 |
assertEq(manager.getSyncedReserves(), 0); |
||
| 67 | |||
| 68 |
swapRouter.swap(key, SWAP_PARAMS, testSettings, new bytes(0)); |
||
| 69 |
(uint256 balanceCurrency0) = currency0.balanceOf(address(manager)); |
||
| 70 |
manager.sync(currency0); |
||
| 71 |
assertEq(manager.getSyncedReserves(), balanceCurrency0); // Reserves are up to date since settle + sync was called. |
||
| 72 |
} |
||
| 73 | |||
| 74 |
function test_settle_withNoStartingBalance() public noIsolate {
|
||
| 75 |
assertEq(currency2.balanceOf(address(manager)), uint256(0)); |
||
| 76 | |||
| 77 |
(Currency cur0, Currency cur1) = currency0 < currency2 ? (currency0, currency2) : (currency2, currency0); |
||
| 78 |
PoolKey memory key2 = |
||
| 79 |
PoolKey({currency0: cur0, currency1: cur1, fee: 3000, tickSpacing: 60, hooks: IHooks(address(0))});
|
||
| 80 | |||
| 81 |
manager.initialize(key2, SQRT_PRICE_1_1, new bytes(0)); |
||
| 82 | |||
| 83 |
// Sync has not been called. |
||
| 84 |
assertEq(manager.getSyncedReserves(), 0); |
||
| 85 |
modifyLiquidityRouter.modifyLiquidity(key2, IPoolManager.ModifyLiquidityParams(-60, 60, 100, 0), new bytes(0)); |
||
| 86 |
(uint256 balanceCurrency2) = currency2.balanceOf(address(manager)); |
||
| 87 |
manager.sync(currency2); |
||
| 88 |
assertEq(manager.getSyncedReserves(), balanceCurrency2); |
||
| 89 |
} |
||
| 90 | |||
| 91 |
function test_settle_payOnBehalf(address taker, uint256 amount) public {
|
||
| 92 |
vm.assume(taker != address(router)); |
||
| 93 |
amount = bound(amount, 1, uint256(int256(type(int128).max))); |
||
| 94 |
MockERC20(Currency.unwrap(currency2)).approve(address(router), type(uint256).max); |
||
| 95 |
MockERC20(Currency.unwrap(currency2)).mint(address(manager), amount); |
||
| 96 | |||
| 97 |
Actions[] memory actions = new Actions[](6); |
||
| 98 |
bytes[] memory params = new bytes[](6); |
||
| 99 | |||
| 100 |
actions[0] = Actions.PRANK_TAKE_FROM; |
||
| 101 |
params[0] = abi.encode(currency2, taker, taker, amount); |
||
| 102 | |||
| 103 |
actions[1] = Actions.ASSERT_DELTA_EQUALS; |
||
| 104 |
params[1] = abi.encode(currency2, taker, int256(amount) * -1); |
||
| 105 | |||
| 106 |
actions[2] = Actions.SYNC; |
||
| 107 |
params[2] = abi.encode(currency2); |
||
| 108 | |||
| 109 |
actions[3] = Actions.TRANSFER_FROM; |
||
| 110 |
params[3] = abi.encode(currency2, address(this), address(manager), amount); |
||
| 111 | |||
| 112 |
actions[4] = Actions.SETTLE_FOR; |
||
| 113 |
params[4] = abi.encode(taker); |
||
| 114 | |||
| 115 |
actions[5] = Actions.ASSERT_DELTA_EQUALS; |
||
| 116 |
params[5] = abi.encode(currency2, taker, 0); |
||
| 117 | |||
| 118 |
router.executeActions(actions, params); |
||
| 119 |
} |
||
| 120 | |||
| 121 |
/// @notice When there is no balance and reserves are set to 0, no delta should be applied. |
||
| 122 |
function test_settle_noBalanceInPool_shouldNotApplyDelta() public noIsolate {
|
||
| 123 |
assertEq(currency2.balanceOf(address(manager)), uint256(0)); |
||
| 124 | |||
| 125 |
manager.sync(currency2); |
||
| 126 |
assertEq(manager.getSyncedReserves(), 0); |
||
| 127 | |||
| 128 |
Actions[] memory actions = new Actions[](2); |
||
| 129 |
bytes[] memory params = new bytes[](2); |
||
| 130 | |||
| 131 |
actions[0] = Actions.SETTLE; |
||
| 132 | |||
| 133 |
actions[1] = Actions.ASSERT_DELTA_EQUALS; |
||
| 134 |
params[1] = abi.encode(currency2, address(router), 0); |
||
| 135 | |||
| 136 |
router.executeActions(actions, params); |
||
| 137 |
} |
||
| 138 | |||
| 139 |
/// @notice When there is a balance, no delta should be applied. |
||
| 140 |
function test_settle_balanceInPool_shouldNotApplyDelta() public noIsolate {
|
||
| 141 |
uint256 currency0Balance = currency0.balanceOf(address(manager)); |
||
| 142 | |||
| 143 |
// Sync has not been called. |
||
| 144 |
assertEq(manager.getSyncedReserves(), 0); |
||
| 145 | |||
| 146 |
manager.sync(currency0); |
||
| 147 |
assertEq(manager.getSyncedReserves(), currency0Balance); |
||
| 148 | |||
| 149 |
Actions[] memory actions = new Actions[](2); |
||
| 150 |
bytes[] memory params = new bytes[](2); |
||
| 151 | |||
| 152 |
actions[0] = Actions.SETTLE; |
||
| 153 | |||
| 154 |
actions[1] = Actions.ASSERT_DELTA_EQUALS; |
||
| 155 |
params[1] = abi.encode(currency0, address(router), 0); |
||
| 156 | |||
| 157 |
router.executeActions(actions, params); |
||
| 158 |
} |
||
| 159 | |||
| 160 |
// @notice This tests expected behavior if you DO NOT call sync before a non native settle. (ie. Do not interact with the pool manager properly. You can lose funds.) |
||
| 161 |
function test_settle_nonNative_withoutSync_loseFunds() public noIsolate {
|
||
| 162 |
MockERC20(Currency.unwrap(currency0)).approve(address(router), type(uint256).max); |
||
| 163 |
uint256 managerCurrency0BalanceBefore = currency0.balanceOf(address(manager)); |
||
| 164 |
uint256 userCurrency0BalanceBefore = currency0.balanceOf(address(this)); |
||
| 165 | |||
| 166 |
Actions[] memory actions = new Actions[](9); |
||
| 167 |
bytes[] memory params = new bytes[](9); |
||
| 168 | |||
| 169 |
manager.sync(currency0); |
||
| 170 |
snapStart("getReserves");
|
||
| 171 |
uint256 reserves = manager.getSyncedReserves(); |
||
| 172 |
snapEnd(); |
||
| 173 |
assertEq(reserves, managerCurrency0BalanceBefore); // reserves are 100. |
||
| 174 | |||
| 175 |
actions[0] = Actions.TAKE; |
||
| 176 |
params[0] = abi.encode(currency0, address(this), 10); |
||
| 177 | |||
| 178 |
// Assert that the delta open on the router is -10. (The user owes 10 to the pool). |
||
| 179 |
actions[1] = Actions.ASSERT_DELTA_EQUALS; |
||
| 180 |
params[1] = abi.encode(currency0, address(router), -10); |
||
| 181 | |||
| 182 |
actions[2] = Actions.TRANSFER_FROM; // NOT syned before sending tokens |
||
| 183 |
params[2] = abi.encode(currency0, address(this), manager, 10); |
||
| 184 | |||
| 185 |
actions[3] = Actions.SETTLE; // calling settle without sync is expecting a native token, but msg.value == 0 so it settles for 0. |
||
| 186 | |||
| 187 |
actions[4] = Actions.ASSERT_DELTA_EQUALS; |
||
| 188 |
params[4] = abi.encode(currency0, address(router), -10); |
||
| 189 | |||
| 190 |
actions[5] = Actions.SYNC; |
||
| 191 |
params[5] = abi.encode(currency0); |
||
| 192 | |||
| 193 |
// To now settle the delta, the user owes 10 to the pool. |
||
| 194 |
actions[6] = Actions.TRANSFER_FROM; |
||
| 195 |
params[6] = abi.encode(currency0, address(this), manager, 10); |
||
| 196 | |||
| 197 |
actions[7] = Actions.SETTLE; |
||
| 198 | |||
| 199 |
actions[8] = Actions.ASSERT_DELTA_EQUALS; |
||
| 200 |
params[8] = abi.encode(currency0, address(router), 0); |
||
| 201 | |||
| 202 |
router.executeActions(actions, params); |
||
| 203 | |||
| 204 |
// The manager gained 10 currency0. |
||
| 205 |
assertEq(currency0.balanceOf(address(manager)), managerCurrency0BalanceBefore + 10); |
||
| 206 |
// The user lost 10 currency0, and can never claim it back. |
||
| 207 |
assertEq(currency0.balanceOf(address(this)), userCurrency0BalanceBefore - 10); |
||
| 208 |
} |
||
| 209 | |||
| 210 |
function test_settle_failsWithNativeERC20IfNotSyncedInOrder(uint256 value) public noIsolate {
|
||
| 211 |
value = bound(value, 1, uint256(int256(type(int128).max / 2))); |
||
| 212 |
vm.deal(address(this), value); |
||
| 213 |
vm.deal(address(manager), value); |
||
| 214 |
NativeERC20 nativeERC20 = new NativeERC20(); |
||
| 215 | |||
| 216 |
manager.sync(Currency.wrap(address(nativeERC20))); |
||
| 217 | |||
| 218 |
Actions[] memory actions = new Actions[](1); |
||
| 219 |
bytes[] memory params = new bytes[](1); |
||
| 220 | |||
| 221 |
// Revert with NonZeroNativeValue |
||
| 222 |
actions[0] = Actions.SETTLE_NATIVE; |
||
| 223 |
params[0] = abi.encode(value); |
||
| 224 | |||
| 225 |
vm.expectRevert(IPoolManager.NonZeroNativeValue.selector); |
||
| 226 |
router.executeActions{value: value}(actions, params);
|
||
| 227 | |||
| 228 |
// Reference only - see OZ C01 report - previous test confirming vulnerability |
||
| 229 |
// uint256 balanceBefore = address(this).balance; |
||
| 230 | |||
| 231 |
// actions[1] = Actions.SETTLE; |
||
| 232 |
// params[1] = abi.encode(Currency.wrap(address(nativeERC20))); |
||
| 233 | |||
| 234 |
// actions[2] = Actions.ASSERT_DELTA_EQUALS; |
||
| 235 |
// params[2] = abi.encode(Currency.wrap(address(0)), address(router), value); |
||
| 236 | |||
| 237 |
// actions[3] = Actions.ASSERT_DELTA_EQUALS; |
||
| 238 |
// params[3] = abi.encode(Currency.wrap(address(nativeERC20)), address(router), value); |
||
| 239 | |||
| 240 |
// actions[4] = Actions.TAKE; |
||
| 241 |
// params[4] = abi.encode(Currency.wrap(address(0)), address(this), value); |
||
| 242 | |||
| 243 |
// actions[5] = Actions.TAKE; |
||
| 244 |
// params[5] = abi.encode(Currency.wrap(address(nativeERC20)), address(this), value); |
||
| 245 | |||
| 246 |
// uint256 balanceAfter = address(this).balance; |
||
| 247 |
// assertEq(balanceAfter - balanceBefore, value); |
||
| 248 |
} |
||
| 249 |
} |
||
| 250 |
| Lines covered: | 0 / 214 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {stdError} from "forge-std/StdError.sol";
|
||
| 6 |
import {GasSnapshot} from "../lib/forge-gas-snapshot/src/GasSnapshot.sol";
|
||
| 7 |
import {Constants} from "./utils/Constants.sol";
|
||
| 8 |
import {Pool} from "../src/libraries/Pool.sol";
|
||
| 9 |
import {TickMath} from "../src/libraries/TickMath.sol";
|
||
| 10 | |||
| 11 |
contract LiquidityMathRef {
|
||
| 12 |
function addDelta(uint128 x, int128 y) external pure returns (uint128) {
|
||
| 13 |
return y < 0 ? x - uint128(-y) : x + uint128(y); |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function addDelta(bool upper, int128 liquidityNetBefore, int128 liquidityDelta) |
||
| 17 |
external |
||
| 18 |
pure |
||
| 19 |
returns (int128 liquidityNet) |
||
| 20 |
{
|
||
| 21 |
liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta; |
||
| 22 |
} |
||
| 23 |
} |
||
| 24 | |||
| 25 |
contract TickTest is Test, GasSnapshot {
|
||
| 26 |
using Pool for Pool.State; |
||
| 27 | |||
| 28 |
int24 constant LOW_TICK_SPACING = 10; |
||
| 29 |
int24 constant MEDIUM_TICK_SPACING = 60; |
||
| 30 |
int24 constant HIGH_TICK_SPACING = 200; |
||
| 31 | |||
| 32 |
Pool.State public pool; |
||
| 33 | |||
| 34 |
LiquidityMathRef internal liquidityMath; |
||
| 35 | |||
| 36 |
function setUp() public {
|
||
| 37 |
liquidityMath = new LiquidityMathRef(); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function ticks(int24 tick) internal view returns (Pool.TickInfo memory) {
|
||
| 41 |
return pool.ticks[tick]; |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function tickBitmap(int16 word) internal view returns (uint256) {
|
||
| 45 |
return pool.tickBitmap[word]; |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128) {
|
||
| 49 |
return Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function setTick(int24 tick, Pool.TickInfo memory info) internal {
|
||
| 53 |
pool.ticks[tick] = info; |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function setTickBitmap(int16 word, uint256 bitmap) internal {
|
||
| 57 |
pool.tickBitmap[word] = bitmap; |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function getFeeGrowthInside( |
||
| 61 |
int24 tickLower, |
||
| 62 |
int24 tickUpper, |
||
| 63 |
int24 tickCurrent, |
||
| 64 |
uint256 feeGrowthGlobal0X128, |
||
| 65 |
uint256 feeGrowthGlobal1X128 |
||
| 66 |
) internal returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) {
|
||
| 67 |
pool.slot0 = pool.slot0.setTick(tickCurrent); |
||
| 68 |
pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128; |
||
| 69 |
pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128; |
||
| 70 |
return pool.getFeeGrowthInside(tickLower, tickUpper); |
||
| 71 |
} |
||
| 72 | |||
| 73 |
function update( |
||
| 74 |
int24 tick, |
||
| 75 |
int24 tickCurrent, |
||
| 76 |
int128 liquidityDelta, |
||
| 77 |
uint256 feeGrowthGlobal0X128, |
||
| 78 |
uint256 feeGrowthGlobal1X128, |
||
| 79 |
bool upper |
||
| 80 |
) internal returns (bool flipped, uint128 liquidityGrossAfter) {
|
||
| 81 |
pool.slot0 = pool.slot0.setTick(tickCurrent); |
||
| 82 |
pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128; |
||
| 83 |
pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128; |
||
| 84 |
return pool.updateTick(tick, liquidityDelta, upper); |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function clear(int24 tick) internal {
|
||
| 88 |
pool.clearTick(tick); |
||
| 89 |
} |
||
| 90 | |||
| 91 |
function cross(int24 tick, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) |
||
| 92 |
internal |
||
| 93 |
returns (int128 liquidityNet) |
||
| 94 |
{
|
||
| 95 |
return pool.crossTick(tick, feeGrowthGlobal0X128, feeGrowthGlobal1X128); |
||
| 96 |
} |
||
| 97 | |||
| 98 |
function getMinTick(int24 tickSpacing) internal pure returns (int256) {
|
||
| 99 |
return (TickMath.MIN_TICK / tickSpacing) * tickSpacing; |
||
| 100 |
} |
||
| 101 | |||
| 102 |
function getMaxTick(int24 tickSpacing) internal pure returns (int256) {
|
||
| 103 |
return (TickMath.MAX_TICK / tickSpacing) * tickSpacing; |
||
| 104 |
} |
||
| 105 | |||
| 106 |
function checkCantOverflow(int24 tickSpacing, uint128 maxLiquidityPerTick) internal pure {
|
||
| 107 |
assertLe( |
||
| 108 |
uint256( |
||
| 109 |
uint256(maxLiquidityPerTick) |
||
| 110 |
* uint256((getMaxTick(tickSpacing) - getMinTick(tickSpacing)) / tickSpacing + 1) |
||
| 111 |
), |
||
| 112 |
uint256(Constants.MAX_UINT128) |
||
| 113 |
); |
||
| 114 |
} |
||
| 115 | |||
| 116 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForLowFee() public pure {
|
||
| 117 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(LOW_TICK_SPACING); |
||
| 118 | |||
| 119 |
assertEq(maxLiquidityPerTick, 1917569901783203986719870431555990); |
||
| 120 |
checkCantOverflow(LOW_TICK_SPACING, maxLiquidityPerTick); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMediumFee() public pure {
|
||
| 124 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(MEDIUM_TICK_SPACING); |
||
| 125 | |||
| 126 |
assertEq(maxLiquidityPerTick, 11505743598341114571880798222544994); |
||
| 127 |
checkCantOverflow(MEDIUM_TICK_SPACING, maxLiquidityPerTick); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForHighFee() public pure {
|
||
| 131 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(HIGH_TICK_SPACING); |
||
| 132 | |||
| 133 |
assertEq(maxLiquidityPerTick, 38350317471085141830651933667504588); |
||
| 134 |
checkCantOverflow(HIGH_TICK_SPACING, maxLiquidityPerTick); |
||
| 135 |
} |
||
| 136 | |||
| 137 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMinTickSpacing() public pure {
|
||
| 138 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(TickMath.MIN_TICK_SPACING); |
||
| 139 | |||
| 140 |
assertEq(maxLiquidityPerTick, 191757530477355301479181766273477); |
||
| 141 |
checkCantOverflow(TickMath.MIN_TICK_SPACING, maxLiquidityPerTick); |
||
| 142 |
} |
||
| 143 | |||
| 144 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMaxTickSpacing() public pure {
|
||
| 145 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(TickMath.MAX_TICK_SPACING); |
||
| 146 | |||
| 147 |
assertEq(maxLiquidityPerTick, 6186952125835244790243174680577603844); |
||
| 148 |
checkCantOverflow(TickMath.MAX_TICK_SPACING, maxLiquidityPerTick); |
||
| 149 |
} |
||
| 150 | |||
| 151 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForEntireRange() public pure {
|
||
| 152 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(TickMath.MAX_TICK); |
||
| 153 | |||
| 154 |
assertEq(maxLiquidityPerTick, type(uint128).max / 3); |
||
| 155 |
checkCantOverflow(TickMath.MAX_TICK, maxLiquidityPerTick); |
||
| 156 |
} |
||
| 157 | |||
| 158 |
function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueFor2302() public pure {
|
||
| 159 |
uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(2302); |
||
| 160 | |||
| 161 |
assertEq(maxLiquidityPerTick, 441351967472034323558203122479595605); |
||
| 162 |
checkCantOverflow(2302, maxLiquidityPerTick); |
||
| 163 |
} |
||
| 164 | |||
| 165 |
function testTick_tickSpacingToMaxLiquidityPerTick_gasCostMinTickSpacing() public {
|
||
| 166 |
snapStart("tickSpacingToMaxLiquidityPerTick_gasCostMinTickSpacing");
|
||
| 167 |
tickSpacingToMaxLiquidityPerTick(TickMath.MIN_TICK_SPACING); |
||
| 168 |
snapEnd(); |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function testTick_tickSpacingToMaxLiquidityPerTick_gasCost60TickSpacing() public {
|
||
| 172 |
snapStart("tickSpacingToMaxLiquidityPerTick_gasCost60TickSpacing");
|
||
| 173 |
tickSpacingToMaxLiquidityPerTick(60); |
||
| 174 |
snapEnd(); |
||
| 175 |
} |
||
| 176 | |||
| 177 |
function testTick_tickSpacingToMaxLiquidityPerTick_gasCostMaxTickSpacing() public {
|
||
| 178 |
snapStart("tickSpacingToMaxLiquidityPerTick_gasCostMaxTickSpacing");
|
||
| 179 |
tickSpacingToMaxLiquidityPerTick(TickMath.MAX_TICK_SPACING); |
||
| 180 |
snapEnd(); |
||
| 181 |
} |
||
| 182 | |||
| 183 |
function testTick_getFeeGrowthInside_returnsAllForTwoUninitializedTicksIfTickIsInside() public {
|
||
| 184 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); |
||
| 185 | |||
| 186 |
assertEq(feeGrowthInside0X128, 15); |
||
| 187 |
assertEq(feeGrowthInside1X128, 15); |
||
| 188 |
} |
||
| 189 | |||
| 190 |
function testTick_getFeeGrowthInside_returns0ForTwoUninitializedTicksIfTickIsAbove() public {
|
||
| 191 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 4, 15, 15); |
||
| 192 | |||
| 193 |
assertEq(feeGrowthInside0X128, 0); |
||
| 194 |
assertEq(feeGrowthInside1X128, 0); |
||
| 195 |
} |
||
| 196 | |||
| 197 |
function testTick_getFeeGrowthInside_returns0ForTwoUninitializedTicksIfTickIsBelow() public {
|
||
| 198 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, -4, 15, 15); |
||
| 199 | |||
| 200 |
assertEq(feeGrowthInside0X128, 0); |
||
| 201 |
assertEq(feeGrowthInside1X128, 0); |
||
| 202 |
} |
||
| 203 | |||
| 204 |
function testTick_getFeeGrowthInside_subtractsUpperTickIfBelow() public {
|
||
| 205 |
Pool.TickInfo memory info; |
||
| 206 | |||
| 207 |
info.feeGrowthOutside0X128 = 2; |
||
| 208 |
info.feeGrowthOutside1X128 = 3; |
||
| 209 |
info.liquidityGross = 0; |
||
| 210 |
info.liquidityNet = 0; |
||
| 211 | |||
| 212 |
setTick(2, info); |
||
| 213 | |||
| 214 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); |
||
| 215 | |||
| 216 |
assertEq(feeGrowthInside0X128, 13); |
||
| 217 |
assertEq(feeGrowthInside1X128, 12); |
||
| 218 |
} |
||
| 219 | |||
| 220 |
function testTick_getFeeGrowthInside_subtractsLowerTickIfAbove() public {
|
||
| 221 |
Pool.TickInfo memory info; |
||
| 222 | |||
| 223 |
info.feeGrowthOutside0X128 = 2; |
||
| 224 |
info.feeGrowthOutside1X128 = 3; |
||
| 225 |
info.liquidityGross = 0; |
||
| 226 |
info.liquidityNet = 0; |
||
| 227 | |||
| 228 |
setTick(-2, info); |
||
| 229 | |||
| 230 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); |
||
| 231 | |||
| 232 |
assertEq(feeGrowthInside0X128, 13); |
||
| 233 |
assertEq(feeGrowthInside1X128, 12); |
||
| 234 |
} |
||
| 235 | |||
| 236 |
function testTick_getFeeGrowthInside_subtractsUpperAndLowerTickIfInside() public {
|
||
| 237 |
Pool.TickInfo memory info; |
||
| 238 | |||
| 239 |
info.feeGrowthOutside0X128 = 2; |
||
| 240 |
info.feeGrowthOutside1X128 = 3; |
||
| 241 |
info.liquidityGross = 0; |
||
| 242 |
info.liquidityNet = 0; |
||
| 243 | |||
| 244 |
setTick(-2, info); |
||
| 245 | |||
| 246 |
info.feeGrowthOutside0X128 = 4; |
||
| 247 |
info.feeGrowthOutside1X128 = 1; |
||
| 248 |
info.liquidityGross = 0; |
||
| 249 |
info.liquidityNet = 0; |
||
| 250 | |||
| 251 |
setTick(2, info); |
||
| 252 | |||
| 253 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); |
||
| 254 | |||
| 255 |
assertEq(feeGrowthInside0X128, 9); |
||
| 256 |
assertEq(feeGrowthInside1X128, 11); |
||
| 257 |
} |
||
| 258 | |||
| 259 |
function testTick_getFeeGrowthInside_worksCorrectlyWithOverflowOnInsideTick() public {
|
||
| 260 |
Pool.TickInfo memory info; |
||
| 261 | |||
| 262 |
info.feeGrowthOutside0X128 = Constants.MAX_UINT256 - 3; |
||
| 263 |
info.feeGrowthOutside1X128 = Constants.MAX_UINT256 - 2; |
||
| 264 |
info.liquidityGross = 0; |
||
| 265 |
info.liquidityNet = 0; |
||
| 266 | |||
| 267 |
setTick(-2, info); |
||
| 268 | |||
| 269 |
info.feeGrowthOutside0X128 = 3; |
||
| 270 |
info.feeGrowthOutside1X128 = 5; |
||
| 271 |
info.liquidityGross = 0; |
||
| 272 |
info.liquidityNet = 0; |
||
| 273 | |||
| 274 |
setTick(2, info); |
||
| 275 | |||
| 276 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15); |
||
| 277 | |||
| 278 |
assertEq(feeGrowthInside0X128, 16); |
||
| 279 |
assertEq(feeGrowthInside1X128, 13); |
||
| 280 |
} |
||
| 281 | |||
| 282 |
function testTick_update_flipsFromZeroToNonzero() public {
|
||
| 283 |
(bool flipped, uint128 liquidityGrossAfter) = update(0, 0, 1, 0, 0, false); |
||
| 284 | |||
| 285 |
assertEq(flipped, true); |
||
| 286 |
assertEq(liquidityGrossAfter, 1); |
||
| 287 |
} |
||
| 288 | |||
| 289 |
function testTick_update_doesNotFlipFromNonzeroToGreaterNonzero() public {
|
||
| 290 |
update(0, 0, 1, 0, 0, false); |
||
| 291 |
(bool flipped, uint128 liquidityGrossAfter) = update(0, 0, 1, 0, 0, false); |
||
| 292 | |||
| 293 |
assertEq(flipped, false); |
||
| 294 |
assertEq(liquidityGrossAfter, 2); |
||
| 295 |
} |
||
| 296 | |||
| 297 |
function testTick_update_flipsFromNonzeroToZero() public {
|
||
| 298 |
update(0, 0, 1, 0, 0, false); |
||
| 299 |
(bool flipped, uint128 liquidityGrossAfter) = update(0, 0, -1, 0, 0, false); |
||
| 300 | |||
| 301 |
assertEq(flipped, true); |
||
| 302 |
assertEq(liquidityGrossAfter, 0); |
||
| 303 |
} |
||
| 304 | |||
| 305 |
function testTick_update_doesNotFlipFromNonzeroToLesserZero() public {
|
||
| 306 |
update(0, 0, 2, 0, 0, false); |
||
| 307 |
(bool flipped, uint128 liquidityGrossAfter) = update(0, 0, -1, 0, 0, false); |
||
| 308 | |||
| 309 |
assertEq(flipped, false); |
||
| 310 |
assertEq(liquidityGrossAfter, 1); |
||
| 311 |
} |
||
| 312 | |||
| 313 |
function testTick_update_netsTheLiquidityBasedOnUpperFlag() public {
|
||
| 314 |
Pool.TickInfo memory tickInfo; |
||
| 315 | |||
| 316 |
update(0, 0, 2, 0, 0, false); |
||
| 317 |
update(0, 0, 1, 0, 0, true); |
||
| 318 |
update(0, 0, 3, 0, 0, true); |
||
| 319 |
update(0, 0, 1, 0, 0, false); |
||
| 320 |
tickInfo = ticks(0); |
||
| 321 | |||
| 322 |
assertEq(tickInfo.liquidityGross, 2 + 1 + 3 + 1); |
||
| 323 |
assertEq(tickInfo.liquidityNet, 2 - 1 - 3 + 1); |
||
| 324 |
} |
||
| 325 | |||
| 326 |
function testTick_update_revertsOnOverflowLiquidityGross() public {
|
||
| 327 |
update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false); |
||
| 328 | |||
| 329 |
vm.expectRevert(); |
||
| 330 |
update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false); |
||
| 331 |
} |
||
| 332 | |||
| 333 |
function testTick_update_assumesAllGrowthHappensBelowTicksLteCurrentTick() public {
|
||
| 334 |
Pool.TickInfo memory tickInfo; |
||
| 335 | |||
| 336 |
update(1, 1, 1, 1, 2, false); |
||
| 337 |
tickInfo = ticks(1); |
||
| 338 | |||
| 339 |
assertEq(tickInfo.feeGrowthOutside0X128, 1); |
||
| 340 |
assertEq(tickInfo.feeGrowthOutside1X128, 2); |
||
| 341 |
} |
||
| 342 | |||
| 343 |
function testTick_update_doesNotSetAnyGrowthFieldsIfTickIsAlreadyInitialized() public {
|
||
| 344 |
Pool.TickInfo memory tickInfo; |
||
| 345 | |||
| 346 |
update(1, 1, 1, 1, 2, false); |
||
| 347 |
update(1, 1, 1, 6, 7, false); |
||
| 348 |
tickInfo = ticks(1); |
||
| 349 | |||
| 350 |
assertEq(tickInfo.feeGrowthOutside0X128, 1); |
||
| 351 |
assertEq(tickInfo.feeGrowthOutside1X128, 2); |
||
| 352 |
} |
||
| 353 | |||
| 354 |
function testTick_update_doesNotSetAnyGrowthFieldsForTicksGtCurrentTick() public {
|
||
| 355 |
Pool.TickInfo memory tickInfo; |
||
| 356 | |||
| 357 |
update(2, 1, 1, 1, 2, false); |
||
| 358 |
tickInfo = ticks(2); |
||
| 359 | |||
| 360 |
assertEq(tickInfo.feeGrowthOutside0X128, 0); |
||
| 361 |
assertEq(tickInfo.feeGrowthOutside1X128, 0); |
||
| 362 |
} |
||
| 363 | |||
| 364 |
function testTick_update_liquidityParsing_parsesMaxUint128StoredLiquidityGrossBeforeUpdate() public {
|
||
| 365 |
Pool.TickInfo memory info; |
||
| 366 | |||
| 367 |
info.feeGrowthOutside0X128 = 0; |
||
| 368 |
info.feeGrowthOutside1X128 = 0; |
||
| 369 |
info.liquidityGross = Constants.MAX_UINT128; |
||
| 370 |
info.liquidityNet = 0; |
||
| 371 | |||
| 372 |
setTick(2, info); |
||
| 373 |
update(2, 1, -1, 1, 2, false); |
||
| 374 | |||
| 375 |
info = ticks(2); |
||
| 376 | |||
| 377 |
assertEq(info.liquidityGross, Constants.MAX_UINT128 - 1); |
||
| 378 |
assertEq(info.liquidityNet, -1); |
||
| 379 |
} |
||
| 380 | |||
| 381 |
function testTick_update_liquidityParsing_parsesMaxUint128StoredLiquidityGrossAfterUpdate() public {
|
||
| 382 |
Pool.TickInfo memory info; |
||
| 383 | |||
| 384 |
info.feeGrowthOutside0X128 = 0; |
||
| 385 |
info.feeGrowthOutside1X128 = 0; |
||
| 386 |
info.liquidityGross = (Constants.MAX_UINT128 / 2) + 1; |
||
| 387 |
info.liquidityNet = 0; |
||
| 388 | |||
| 389 |
setTick(2, info); |
||
| 390 | |||
| 391 |
update(2, 1, int128(Constants.MAX_UINT128 / 2), 1, 2, false); |
||
| 392 | |||
| 393 |
info = ticks(2); |
||
| 394 | |||
| 395 |
assertEq(info.liquidityGross, Constants.MAX_UINT128); |
||
| 396 |
assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2)); |
||
| 397 |
} |
||
| 398 | |||
| 399 |
function testTick_update_liquidityParsing_parsesMaxInt128StoredLiquidityGrossBeforeUpdate() public {
|
||
| 400 |
Pool.TickInfo memory info; |
||
| 401 | |||
| 402 |
info.feeGrowthOutside0X128 = 0; |
||
| 403 |
info.feeGrowthOutside1X128 = 0; |
||
| 404 |
info.liquidityGross = 1; |
||
| 405 |
info.liquidityNet = int128(Constants.MAX_UINT128 / 2); |
||
| 406 | |||
| 407 |
setTick(2, info); |
||
| 408 |
update(2, 1, -1, 1, 2, false); |
||
| 409 | |||
| 410 |
info = ticks(2); |
||
| 411 | |||
| 412 |
assertEq(info.liquidityGross, 0); |
||
| 413 |
assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2 - 1)); |
||
| 414 |
} |
||
| 415 | |||
| 416 |
function testTick_update_liquidityParsing_parsesMaxInt128StoredLiquidityGrossAfterUpdate() public {
|
||
| 417 |
Pool.TickInfo memory info; |
||
| 418 | |||
| 419 |
info.feeGrowthOutside0X128 = 0; |
||
| 420 |
info.feeGrowthOutside1X128 = 0; |
||
| 421 |
info.liquidityGross = 0; |
||
| 422 |
info.liquidityNet = int128(Constants.MAX_UINT128 / 2 - 1); |
||
| 423 | |||
| 424 |
setTick(2, info); |
||
| 425 | |||
| 426 |
update(2, 1, 1, 1, 2, false); |
||
| 427 | |||
| 428 |
info = ticks(2); |
||
| 429 | |||
| 430 |
assertEq(info.liquidityGross, 1); |
||
| 431 |
assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2)); |
||
| 432 |
} |
||
| 433 | |||
| 434 |
function testTick_update_fuzz(uint128 liquidityGross, int128 liquidityNet, int128 liquidityDelta, bool upper) |
||
| 435 |
public |
||
| 436 |
{
|
||
| 437 |
try liquidityMath.addDelta(liquidityGross, liquidityDelta) returns (uint128 liquidityGrossAfter) {
|
||
| 438 |
try liquidityMath.addDelta(upper, liquidityNet, liquidityDelta) returns (int128 liquidityNetAfter) {
|
||
| 439 |
Pool.TickInfo memory info = Pool.TickInfo({
|
||
| 440 |
liquidityGross: liquidityGross, |
||
| 441 |
liquidityNet: liquidityNet, |
||
| 442 |
feeGrowthOutside0X128: 0, |
||
| 443 |
feeGrowthOutside1X128: 0 |
||
| 444 |
}); |
||
| 445 | |||
| 446 |
setTick(2, info); |
||
| 447 |
update({
|
||
| 448 |
tick: 2, |
||
| 449 |
tickCurrent: 1, |
||
| 450 |
liquidityDelta: liquidityDelta, |
||
| 451 |
feeGrowthGlobal0X128: 0, |
||
| 452 |
feeGrowthGlobal1X128: 0, |
||
| 453 |
upper: upper |
||
| 454 |
}); |
||
| 455 | |||
| 456 |
info = ticks(2); |
||
| 457 | |||
| 458 |
assertEq(info.liquidityGross, liquidityGrossAfter); |
||
| 459 |
assertEq(info.liquidityNet, liquidityNetAfter); |
||
| 460 |
} catch (bytes memory reason) {
|
||
| 461 |
assertEq(reason, stdError.arithmeticError); |
||
| 462 |
} |
||
| 463 |
} catch (bytes memory reason) {
|
||
| 464 |
assertEq(reason, stdError.arithmeticError); |
||
| 465 |
} |
||
| 466 |
} |
||
| 467 | |||
| 468 |
function testTick_clear_deletesAllTheDataInTheTick() public {
|
||
| 469 |
Pool.TickInfo memory info; |
||
| 470 | |||
| 471 |
info.feeGrowthOutside0X128 = 1; |
||
| 472 |
info.feeGrowthOutside1X128 = 2; |
||
| 473 |
info.liquidityGross = 3; |
||
| 474 |
info.liquidityNet = 4; |
||
| 475 | |||
| 476 |
setTick(2, info); |
||
| 477 | |||
| 478 |
clear(2); |
||
| 479 | |||
| 480 |
info = ticks(2); |
||
| 481 | |||
| 482 |
assertEq(info.feeGrowthOutside0X128, 0); |
||
| 483 |
assertEq(info.feeGrowthOutside1X128, 0); |
||
| 484 |
assertEq(info.liquidityGross, 0); |
||
| 485 |
assertEq(info.liquidityNet, 0); |
||
| 486 |
} |
||
| 487 | |||
| 488 |
function testTick_cross_flipsTheGrowthVariables() public {
|
||
| 489 |
Pool.TickInfo memory info; |
||
| 490 | |||
| 491 |
info.feeGrowthOutside0X128 = 1; |
||
| 492 |
info.feeGrowthOutside1X128 = 2; |
||
| 493 |
info.liquidityGross = 3; |
||
| 494 |
info.liquidityNet = 4; |
||
| 495 | |||
| 496 |
setTick(2, info); |
||
| 497 | |||
| 498 |
cross(2, 7, 9); |
||
| 499 | |||
| 500 |
info = ticks(2); |
||
| 501 | |||
| 502 |
assertEq(info.feeGrowthOutside0X128, 6); |
||
| 503 |
assertEq(info.feeGrowthOutside1X128, 7); |
||
| 504 |
} |
||
| 505 | |||
| 506 |
function testTick_cross_twoFlipsAreNoOp() public {
|
||
| 507 |
Pool.TickInfo memory info; |
||
| 508 | |||
| 509 |
info.feeGrowthOutside0X128 = 1; |
||
| 510 |
info.feeGrowthOutside1X128 = 2; |
||
| 511 |
info.liquidityGross = 3; |
||
| 512 |
info.liquidityNet = 4; |
||
| 513 | |||
| 514 |
setTick(2, info); |
||
| 515 | |||
| 516 |
cross(2, 7, 9); |
||
| 517 |
cross(2, 7, 9); |
||
| 518 | |||
| 519 |
info = ticks(2); |
||
| 520 | |||
| 521 |
assertEq(info.feeGrowthOutside0X128, 1); |
||
| 522 |
assertEq(info.feeGrowthOutside1X128, 2); |
||
| 523 |
} |
||
| 524 | |||
| 525 |
function test_getPoolTickInfo(int24 tick, Pool.TickInfo memory info) public {
|
||
| 526 |
setTick(tick, info); |
||
| 527 |
Pool.TickInfo memory actualInfo = ticks(tick); |
||
| 528 |
assertEq(actualInfo.liquidityGross, info.liquidityGross); |
||
| 529 |
assertEq(actualInfo.liquidityNet, info.liquidityNet); |
||
| 530 |
assertEq(actualInfo.feeGrowthOutside0X128, info.feeGrowthOutside0X128); |
||
| 531 |
assertEq(actualInfo.feeGrowthOutside1X128, info.feeGrowthOutside1X128); |
||
| 532 |
} |
||
| 533 | |||
| 534 |
function test_getPoolBitmapInfo(int16 word, uint256 bitmap) public {
|
||
| 535 |
setTickBitmap(word, bitmap); |
||
| 536 |
assertEq(tickBitmap(word), bitmap); |
||
| 537 |
} |
||
| 538 | |||
| 539 |
function testTick_tickSpacingToParametersInvariants_fuzz(int24 tickSpacing) public pure {
|
||
| 540 |
tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); |
||
| 541 | |||
| 542 |
int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing; |
||
| 543 |
int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing; |
||
| 544 | |||
| 545 |
uint128 maxLiquidityPerTick = Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing); |
||
| 546 | |||
| 547 |
// symmetry around 0 tick |
||
| 548 |
assertEq(maxTick, -minTick); |
||
| 549 |
// positive max tick |
||
| 550 |
assertGt(maxTick, 0); |
||
| 551 |
// divisibility |
||
| 552 |
assertEq((maxTick - minTick) % tickSpacing, 0); |
||
| 553 | |||
| 554 |
uint256 numTicks = uint256(int256((maxTick - minTick) / tickSpacing)) + 1; |
||
| 555 | |||
| 556 |
// sum of max liquidity on each tick is at most the cap |
||
| 557 |
assertGe(type(uint128).max, uint256(maxLiquidityPerTick) * numTicks); |
||
| 558 |
} |
||
| 559 |
} |
||
| 560 |
| Lines covered: | 0 / 55 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 5 |
import {Test} from "forge-std/Test.sol";
|
||
| 6 |
import {BitMath} from "../../src/libraries/BitMath.sol";
|
||
| 7 | |||
| 8 |
contract TestBitMath is Test, GasSnapshot {
|
||
| 9 |
function test_mostSignificantBit_revertsWhenZero() public {
|
||
| 10 |
vm.expectRevert(); |
||
| 11 |
BitMath.mostSignificantBit(0); |
||
| 12 |
} |
||
| 13 | |||
| 14 |
function test_mostSignificantBit_one() public pure {
|
||
| 15 |
assertEq(BitMath.mostSignificantBit(1), 0); |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function test_mostSignificantBit_two() public pure {
|
||
| 19 |
assertEq(BitMath.mostSignificantBit(2), 1); |
||
| 20 |
} |
||
| 21 | |||
| 22 |
function test_mostSignificantBit_powersOfTwo() public pure {
|
||
| 23 |
for (uint256 i = 0; i < 255; i++) {
|
||
| 24 |
uint256 x = 1 << i; |
||
| 25 |
assertEq(BitMath.mostSignificantBit(x), i); |
||
| 26 |
} |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function test_mostSignificantBit_maxUint256() public pure {
|
||
| 30 |
assertEq(BitMath.mostSignificantBit(type(uint256).max), 255); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function test_fuzz_mostSignificantBit(uint256 x) public pure {
|
||
| 34 |
vm.assume(x != 0); |
||
| 35 |
assertEq(BitMath.mostSignificantBit(x), mostSignificantBitReference(x)); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function test_invariant_mostSignificantBit(uint256 x) public pure {
|
||
| 39 |
vm.assume(x != 0); |
||
| 40 |
uint8 msb = BitMath.mostSignificantBit(x); |
||
| 41 |
assertGe(x, uint256(2) ** msb); |
||
| 42 |
assertTrue(msb == 255 || x < uint256(2) ** (msb + 1)); |
||
| 43 |
} |
||
| 44 | |||
| 45 |
function test_mostSignificantBit_gas() public {
|
||
| 46 |
snapStart("BitMathMostSignificantBitSmallNumber");
|
||
| 47 |
BitMath.mostSignificantBit(3568); |
||
| 48 |
snapEnd(); |
||
| 49 | |||
| 50 |
snapStart("BitMathMostSignificantBitMaxUint128");
|
||
| 51 |
BitMath.mostSignificantBit(type(uint128).max); |
||
| 52 |
snapEnd(); |
||
| 53 | |||
| 54 |
snapStart("BitMathMostSignificantBitMaxUint256");
|
||
| 55 |
BitMath.mostSignificantBit(type(uint256).max); |
||
| 56 |
snapEnd(); |
||
| 57 |
} |
||
| 58 | |||
| 59 |
function test_leastSignificantBit_revertsWhenZero() public {
|
||
| 60 |
vm.expectRevert(); |
||
| 61 |
BitMath.leastSignificantBit(0); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function test_leastSignificantBit_one() public pure {
|
||
| 65 |
assertEq(BitMath.leastSignificantBit(1), 0); |
||
| 66 |
} |
||
| 67 | |||
| 68 |
function test_leastSignificantBit_two() public pure {
|
||
| 69 |
assertEq(BitMath.leastSignificantBit(2), 1); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function test_leastSignificantBit_powersOfTwo() public pure {
|
||
| 73 |
for (uint256 i = 0; i < 255; i++) {
|
||
| 74 |
uint256 x = 1 << i; |
||
| 75 |
assertEq(BitMath.leastSignificantBit(x), i); |
||
| 76 |
} |
||
| 77 |
} |
||
| 78 | |||
| 79 |
function test_leastSignificantBit_maxUint256() public pure {
|
||
| 80 |
assertEq(BitMath.leastSignificantBit(type(uint256).max), 0); |
||
| 81 |
} |
||
| 82 | |||
| 83 |
function test_fuzz_leastSignificantBit(uint256 x) public pure {
|
||
| 84 |
vm.assume(x != 0); |
||
| 85 |
assertEq(BitMath.leastSignificantBit(x), leastSignificantBitReference(x)); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function test_invariant_leastSignificantBit(uint256 x) public pure {
|
||
| 89 |
vm.assume(x != 0); |
||
| 90 |
uint8 lsb = BitMath.leastSignificantBit(x); |
||
| 91 |
assertNotEq(x & (uint256(2) ** lsb), 0); |
||
| 92 |
assertEq(x & (uint256(2) ** lsb - 1), 0); |
||
| 93 |
} |
||
| 94 | |||
| 95 |
function test_leastSignificantBit_gas() public {
|
||
| 96 |
snapStart("BitMathLeastSignificantBitSmallNumber");
|
||
| 97 |
BitMath.leastSignificantBit(3568); |
||
| 98 |
snapEnd(); |
||
| 99 | |||
| 100 |
snapStart("BitMathLeastSignificantBitMaxUint128");
|
||
| 101 |
BitMath.leastSignificantBit(type(uint128).max); |
||
| 102 |
snapEnd(); |
||
| 103 | |||
| 104 |
snapStart("BitMathLeastSignificantBitMaxUint256");
|
||
| 105 |
BitMath.leastSignificantBit(type(uint256).max); |
||
| 106 |
snapEnd(); |
||
| 107 |
} |
||
| 108 | |||
| 109 |
function mostSignificantBitReference(uint256 x) private pure returns (uint256) {
|
||
| 110 |
uint256 i = 0; |
||
| 111 |
while ((x >>= 1) > 0) {
|
||
| 112 |
++i; |
||
| 113 |
} |
||
| 114 |
return i; |
||
| 115 |
} |
||
| 116 | |||
| 117 |
function leastSignificantBitReference(uint256 x) private pure returns (uint256) {
|
||
| 118 |
require(x > 0, "BitMath: zero has no least significant bit"); |
||
| 119 | |||
| 120 |
uint256 i = 0; |
||
| 121 |
while ((x >> i) & 1 == 0) {
|
||
| 122 |
++i; |
||
| 123 |
} |
||
| 124 |
return i; |
||
| 125 |
} |
||
| 126 |
} |
||
| 127 |
| Lines covered: | 0 / 97 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.19; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {FullMath} from "../../src/libraries/FullMath.sol";
|
||
| 6 | |||
| 7 |
contract FullMathTest is Test {
|
||
| 8 |
using FullMath for uint256; |
||
| 9 | |||
| 10 |
uint256 constant Q128 = 2 ** 128; |
||
| 11 |
uint256 constant MAX_UINT256 = type(uint256).max; |
||
| 12 | |||
| 13 |
function test_fuzz_mulDiv_revertsWith0Denominator(uint256 x, uint256 y) public {
|
||
| 14 |
vm.expectRevert(); |
||
| 15 |
x.mulDiv(y, 0); |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function test_mulDiv_revertsWithOverflowingNumeratorAndZeroDenominator() public {
|
||
| 19 |
vm.expectRevert(); |
||
| 20 |
Q128.mulDiv(Q128, 0); |
||
| 21 |
} |
||
| 22 | |||
| 23 |
function test_mulDiv_revertsIfOutputOverflows() public {
|
||
| 24 |
vm.expectRevert(); |
||
| 25 |
Q128.mulDiv(Q128, 1); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function test_mulDiv_revertsOverflowWithAllMaxInputs() public {
|
||
| 29 |
vm.expectRevert(); |
||
| 30 |
MAX_UINT256.mulDiv(MAX_UINT256, MAX_UINT256 - 1); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function test_mulDiv_validAllMaxInputs() public pure {
|
||
| 34 |
assertEq(MAX_UINT256.mulDiv(MAX_UINT256, MAX_UINT256), MAX_UINT256); |
||
| 35 |
} |
||
| 36 | |||
| 37 |
function test_mulDiv_validWithoutPhantomOverflow() public pure {
|
||
| 38 |
uint256 result = Q128 / 3; |
||
| 39 |
assertEq(Q128.mulDiv(50 * Q128 / 100, 150 * Q128 / 100), result); |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function test_mulDiv_validWithPhantomOverflow() public pure {
|
||
| 43 |
uint256 result = 4375 * Q128 / 1000; |
||
| 44 |
assertEq(Q128.mulDiv(35 * Q128, 8 * Q128), result); |
||
| 45 |
} |
||
| 46 | |||
| 47 |
function test_mulDiv_phantomOverflowRepeatingDecimal() public pure {
|
||
| 48 |
uint256 result = 1 * Q128 / 3; |
||
| 49 |
assertEq(Q128.mulDiv(1000 * Q128, 3000 * Q128), result); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function test_fuzz_mulDiv(uint256 x, uint256 y, uint256 d) public pure {
|
||
| 53 |
vm.assume(d != 0); |
||
| 54 |
vm.assume(y != 0); |
||
| 55 |
x = bound(x, 0, type(uint256).max / y); |
||
| 56 |
assertEq(FullMath.mulDiv(x, y, d), x * y / d); |
||
| 57 |
} |
||
| 58 | |||
| 59 |
function test_fuzz_mulDivRoundingUp_revertsWith0Denominator(uint256 x, uint256 y) public {
|
||
| 60 |
vm.expectRevert(); |
||
| 61 |
x.mulDivRoundingUp(y, 0); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function test_mulDivRoundingUp_validWithAllMaxInputs() public pure {
|
||
| 65 |
assertEq(MAX_UINT256.mulDivRoundingUp(MAX_UINT256, MAX_UINT256), MAX_UINT256); |
||
| 66 |
} |
||
| 67 | |||
| 68 |
function test_mulDivRoundingUp_validWithNoPhantomOverflow() public pure {
|
||
| 69 |
uint256 result = Q128 / 3 + 1; |
||
| 70 |
assertEq(Q128.mulDivRoundingUp(50 * Q128 / 100, 150 * Q128 / 100), result); |
||
| 71 |
} |
||
| 72 | |||
| 73 |
function test_mulDivRoundingUp_validWithPhantomOverflow() public pure {
|
||
| 74 |
uint256 result = 4375 * Q128 / 1000; |
||
| 75 |
assertEq(Q128.mulDiv(35 * Q128, 8 * Q128), result); |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function test_mulDivRoundingUp_validWithPhantomOverflowRepeatingDecimal() public pure {
|
||
| 79 |
uint256 result = 1 * Q128 / 3 + 1; |
||
| 80 |
assertEq(Q128.mulDivRoundingUp(1000 * Q128, 3000 * Q128), result); |
||
| 81 |
} |
||
| 82 | |||
| 83 |
function test_mulDivRoundingUp_revertsIfMulDivOverflows256BitsAfterRoundingUp() public {
|
||
| 84 |
vm.expectRevert(); |
||
| 85 |
FullMath.mulDivRoundingUp(535006138814359, 432862656469423142931042426214547535783388063929571229938474969, 2); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function test_mulDivRoundingUp_revertsIfMulDivOverflows256BitsAfterRoundingUpCase2() public {
|
||
| 89 |
vm.expectRevert(); |
||
| 90 |
FullMath.mulDivRoundingUp( |
||
| 91 |
115792089237316195423570985008687907853269984659341747863450311749907997002549, |
||
| 92 |
115792089237316195423570985008687907853269984659341747863450311749907997002550, |
||
| 93 |
115792089237316195423570985008687907853269984653042931687443039491902864365164 |
||
| 94 |
); |
||
| 95 |
} |
||
| 96 | |||
| 97 |
function test_fuzz_mulDivRoundingUp(uint256 x, uint256 y, uint256 d) public pure {
|
||
| 98 |
vm.assume(d != 0); |
||
| 99 |
vm.assume(y != 0); |
||
| 100 |
x = bound(x, 0, type(uint256).max / y); |
||
| 101 |
uint256 numerator = x * y; |
||
| 102 |
uint256 result = FullMath.mulDivRoundingUp(x, y, d); |
||
| 103 |
if (mulmod(x, y, d) > 0) {
|
||
| 104 |
assertEq(result, numerator / d + 1); |
||
| 105 |
} else {
|
||
| 106 |
assertEq(result, numerator / d); |
||
| 107 |
} |
||
| 108 |
} |
||
| 109 | |||
| 110 |
function test_invariant_mulDivRounding(uint256 x, uint256 y, uint256 d) public pure {
|
||
| 111 |
unchecked {
|
||
| 112 |
vm.assume(d > 0); |
||
| 113 |
vm.assume(!resultOverflows(x, y, d)); |
||
| 114 | |||
| 115 |
uint256 ceiled = FullMath.mulDivRoundingUp(x, y, d); |
||
| 116 | |||
| 117 |
uint256 floored = FullMath.mulDiv(x, y, d); |
||
| 118 | |||
| 119 |
if (mulmod(x, y, d) > 0) {
|
||
| 120 |
assertEq(ceiled - floored, 1); |
||
| 121 |
} else {
|
||
| 122 |
assertEq(ceiled, floored); |
||
| 123 |
} |
||
| 124 |
} |
||
| 125 |
} |
||
| 126 | |||
| 127 |
function test_invariant_mulDiv(uint256 x, uint256 y, uint256 d) public pure {
|
||
| 128 |
unchecked {
|
||
| 129 |
vm.assume(d > 0); |
||
| 130 |
vm.assume(!resultOverflows(x, y, d)); |
||
| 131 |
uint256 z = FullMath.mulDiv(x, y, d); |
||
| 132 |
if (x == 0 || y == 0) {
|
||
| 133 |
assertEq(z, 0); |
||
| 134 |
return; |
||
| 135 |
} |
||
| 136 | |||
| 137 |
// recompute x and y via mulDiv of the result of floor(x*y/d), should always be less than original inputs by < d |
||
| 138 |
uint256 x2 = FullMath.mulDiv(z, d, y); |
||
| 139 |
uint256 y2 = FullMath.mulDiv(z, d, x); |
||
| 140 |
assertLe(x2, x); |
||
| 141 |
assertLe(y2, y); |
||
| 142 | |||
| 143 |
assertLt(x - x2, d); |
||
| 144 |
assertLt(y - y2, d); |
||
| 145 |
} |
||
| 146 |
} |
||
| 147 | |||
| 148 |
function test_invariant_mulDivRoundingUp(uint256 x, uint256 y, uint256 d) external pure {
|
||
| 149 |
unchecked {
|
||
| 150 |
vm.assume(d > 0); |
||
| 151 |
vm.assume(!resultOverflows(x, y, d)); |
||
| 152 |
uint256 z = FullMath.mulDivRoundingUp(x, y, d); |
||
| 153 |
if (x == 0 || y == 0) {
|
||
| 154 |
assertEq(z, 0); |
||
| 155 |
return; |
||
| 156 |
} |
||
| 157 | |||
| 158 |
vm.assume(!resultOverflows(z, d, y)); |
||
| 159 |
vm.assume(!resultOverflows(z, d, x)); |
||
| 160 |
// recompute x and y via mulDiv of the result of ceil(x*y/d), should always be greater than original inputs by < d |
||
| 161 |
uint256 x2 = FullMath.mulDiv(z, d, y); |
||
| 162 |
uint256 y2 = FullMath.mulDiv(z, d, x); |
||
| 163 |
assertGe(x2, x); |
||
| 164 |
assertGe(y2, y); |
||
| 165 | |||
| 166 |
assertLt(x2 - x, d); |
||
| 167 |
assertLt(y2 - y, d); |
||
| 168 |
} |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function test_resultOverflows_helper() public pure {
|
||
| 172 |
assertFalse(resultOverflows(0, 0, 1)); |
||
| 173 |
assertFalse(resultOverflows(1, 0, 1)); |
||
| 174 |
assertFalse(resultOverflows(0, 1, 1)); |
||
| 175 |
assertFalse(resultOverflows(1, 1, 1)); |
||
| 176 |
assertFalse(resultOverflows(10000000, 10000000, 1)); |
||
| 177 |
assertFalse(resultOverflows(Q128, 50 * Q128 / 100, 150 * Q128 / 100)); |
||
| 178 |
assertFalse(resultOverflows(Q128, 35 * Q128, 8 * Q128)); |
||
| 179 |
assertTrue(resultOverflows(type(uint256).max, type(uint256).max, type(uint256).max - 1)); |
||
| 180 |
assertTrue(resultOverflows(Q128, type(uint256).max, 1)); |
||
| 181 |
} |
||
| 182 | |||
| 183 |
function resultOverflows(uint256 x, uint256 y, uint256 d) private pure returns (bool) {
|
||
| 184 |
require(d > 0); |
||
| 185 | |||
| 186 |
// If x or y is zero, the result will be zero, and there's no overflow |
||
| 187 |
if (x == 0 || y == 0) {
|
||
| 188 |
return false; |
||
| 189 |
} |
||
| 190 | |||
| 191 |
// If intermediate multiplication doesn't overflow, there's no overflow |
||
| 192 |
if (x <= type(uint256).max / y) return false; |
||
| 193 | |||
| 194 |
uint256 remainder = mulmod(x, y, type(uint256).max); |
||
| 195 |
uint256 small; |
||
| 196 |
uint256 big; |
||
| 197 |
unchecked {
|
||
| 198 |
small = x * y; |
||
| 199 |
big = (remainder - small) - (remainder < small ? 1 : 0); |
||
| 200 |
} |
||
| 201 | |||
| 202 |
bool mulDivResultOverflows = d <= big; |
||
| 203 |
bool mulDivRoundingUpResultOverflows = mulDivResultOverflows; |
||
| 204 | |||
| 205 |
// must catch edgecase where mulDiv doesn't overflow but roundingUp does |
||
| 206 |
if (!mulDivResultOverflows) {
|
||
| 207 |
mulDivRoundingUpResultOverflows = FullMath.mulDiv(x, y, d) == type(uint256).max; |
||
| 208 |
} |
||
| 209 | |||
| 210 |
return mulDivResultOverflows || mulDivRoundingUpResultOverflows; |
||
| 211 |
} |
||
| 212 |
} |
||
| 213 |
| Lines covered: | 0 / 317 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 5 |
import {Test} from "forge-std/Test.sol";
|
||
| 6 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 7 |
import {Hooks} from "../../src/libraries/Hooks.sol";
|
||
| 8 |
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
|
||
| 9 |
import {MockHooks} from "../../src/test/MockHooks.sol";
|
||
| 10 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 11 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 12 |
import {IHooks} from "../../src/interfaces/IHooks.sol";
|
||
| 13 |
import {Currency} from "../../src/types/Currency.sol";
|
||
| 14 |
import {PoolManager} from "../../src/PoolManager.sol";
|
||
| 15 |
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
|
||
| 16 |
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
|
||
| 17 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 18 |
import {ProtocolFees} from "../../src/ProtocolFees.sol";
|
||
| 19 |
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
|
||
| 20 |
import {PoolKey} from "../../src/types/PoolKey.sol";
|
||
| 21 |
import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
|
||
| 22 |
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
|
||
| 23 |
import {BaseTestHooks} from "../../src/test/BaseTestHooks.sol";
|
||
| 24 |
import {EmptyRevertContract} from "../../src/test/EmptyRevertContract.sol";
|
||
| 25 |
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
|
||
| 26 |
import {Constants} from "../utils/Constants.sol";
|
||
| 27 | |||
| 28 |
contract HooksTest is Test, Deployers, GasSnapshot {
|
||
| 29 |
using PoolIdLibrary for PoolKey; |
||
| 30 |
using Hooks for IHooks; |
||
| 31 |
using StateLibrary for IPoolManager; |
||
| 32 | |||
| 33 |
MockHooks mockHooks; |
||
| 34 |
BaseTestHooks revertingHookImpl; |
||
| 35 | |||
| 36 |
function setUp() public {
|
||
| 37 |
MockHooks impl = new MockHooks(); |
||
| 38 |
vm.etch(Constants.ALL_HOOKS, address(impl).code); |
||
| 39 |
mockHooks = MockHooks(Constants.ALL_HOOKS); |
||
| 40 | |||
| 41 |
revertingHookImpl = new BaseTestHooks(); |
||
| 42 | |||
| 43 |
initializeManagerRoutersAndPoolsWithLiq(mockHooks); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function test_initialize_succeedsWithHook() public {
|
||
| 47 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, new bytes(123)); |
||
| 48 | |||
| 49 |
(uint160 sqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId()); |
||
| 50 |
assertEq(sqrtPriceX96, SQRT_PRICE_1_1); |
||
| 51 |
assertEq(mockHooks.beforeInitializeData(), new bytes(123)); |
||
| 52 |
assertEq(mockHooks.afterInitializeData(), new bytes(123)); |
||
| 53 |
} |
||
| 54 | |||
| 55 |
function test_beforeInitialize_invalidReturn() public {
|
||
| 56 |
mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, bytes4(0xdeadbeef)); |
||
| 57 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 58 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 59 |
} |
||
| 60 | |||
| 61 |
function test_afterInitialize_invalidReturn() public {
|
||
| 62 |
mockHooks.setReturnValue(mockHooks.afterInitialize.selector, bytes4(0xdeadbeef)); |
||
| 63 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 64 |
manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function test_beforeAfterAddLiquidity_beforeAfterRemoveLiquidity_succeedsWithHook() public {
|
||
| 68 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 69 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 70 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 1e18, 0), new bytes(111)); |
||
| 71 |
assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111)); |
||
| 72 |
assertEq(mockHooks.afterAddLiquidityData(), new bytes(111)); |
||
| 73 | |||
| 74 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, -1e18, 0), new bytes(222)); |
||
| 75 |
assertEq(mockHooks.beforeRemoveLiquidityData(), new bytes(222)); |
||
| 76 |
assertEq(mockHooks.afterRemoveLiquidityData(), new bytes(222)); |
||
| 77 |
} |
||
| 78 | |||
| 79 |
function test_beforeAfterAddLiquidity_calledWithPositiveLiquidityDelta() public {
|
||
| 80 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 81 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 82 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 100, 0), new bytes(111)); |
||
| 83 |
assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111)); |
||
| 84 |
assertEq(mockHooks.afterAddLiquidityData(), new bytes(111)); |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function test_beforeAfterRemoveLiquidity_calledWithZeroLiquidityDelta() public {
|
||
| 88 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 89 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 90 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 1e18, 0), new bytes(111)); |
||
| 91 |
assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111)); |
||
| 92 |
assertEq(mockHooks.afterAddLiquidityData(), new bytes(111)); |
||
| 93 | |||
| 94 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 0, 0), new bytes(222)); |
||
| 95 |
assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111)); |
||
| 96 |
assertEq(mockHooks.afterAddLiquidityData(), new bytes(111)); |
||
| 97 |
assertEq(mockHooks.beforeRemoveLiquidityData(), new bytes(222)); |
||
| 98 |
assertEq(mockHooks.afterRemoveLiquidityData(), new bytes(222)); |
||
| 99 |
} |
||
| 100 | |||
| 101 |
function test_beforeAfterRemoveLiquidity_calledWithPositiveLiquidityDelta() public {
|
||
| 102 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 1e18, 0), new bytes(111)); |
||
| 103 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 104 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 105 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, -1e18, 0), new bytes(111)); |
||
| 106 |
assertEq(mockHooks.beforeRemoveLiquidityData(), new bytes(111)); |
||
| 107 |
assertEq(mockHooks.afterRemoveLiquidityData(), new bytes(111)); |
||
| 108 |
} |
||
| 109 | |||
| 110 |
function test_beforeAddLiquidity_invalidReturn() public {
|
||
| 111 |
mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 112 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 113 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 114 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 115 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function test_beforeRemoveLiquidity_invalidReturn() public {
|
||
| 119 |
mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 120 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 121 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 122 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 123 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 124 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 125 |
} |
||
| 126 | |||
| 127 |
function test_afterAddLiquidity_invalidReturn() public {
|
||
| 128 |
mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 129 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 130 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 131 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 132 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 133 |
} |
||
| 134 | |||
| 135 |
function test_afterRemoveLiquidity_invalidReturn() public {
|
||
| 136 |
mockHooks.setReturnValue(mockHooks.afterRemoveLiquidity.selector, bytes4(0xdeadbeef)); |
||
| 137 |
MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18); |
||
| 138 |
MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18); |
||
| 139 |
modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 140 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 141 |
modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES); |
||
| 142 |
} |
||
| 143 | |||
| 144 |
function test_swap_succeedsWithHook() public {
|
||
| 145 |
IPoolManager.SwapParams memory swapParams = |
||
| 146 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 147 | |||
| 148 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 149 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 150 | |||
| 151 |
swapRouter.swap(key, swapParams, testSettings, new bytes(222)); |
||
| 152 |
assertEq(mockHooks.beforeSwapData(), new bytes(222)); |
||
| 153 |
assertEq(mockHooks.afterSwapData(), new bytes(222)); |
||
| 154 |
} |
||
| 155 | |||
| 156 |
function test_beforeSwap_invalidReturn() public {
|
||
| 157 |
mockHooks.setReturnValue(mockHooks.beforeSwap.selector, bytes4(0xdeadbeef)); |
||
| 158 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 159 |
swapRouter.swap( |
||
| 160 |
key, |
||
| 161 |
IPoolManager.SwapParams(false, 100, SQRT_PRICE_1_1 + 60), |
||
| 162 |
PoolSwapTest.TestSettings(true, true), |
||
| 163 |
ZERO_BYTES |
||
| 164 |
); |
||
| 165 |
} |
||
| 166 | |||
| 167 |
function test_afterSwap_invalidReturn() public {
|
||
| 168 |
mockHooks.setReturnValue(mockHooks.afterSwap.selector, bytes4(0xdeadbeef)); |
||
| 169 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 170 |
swapRouter.swap( |
||
| 171 |
key, |
||
| 172 |
IPoolManager.SwapParams(false, 100, SQRT_PRICE_1_1 + 60), |
||
| 173 |
PoolSwapTest.TestSettings(true, true), |
||
| 174 |
ZERO_BYTES |
||
| 175 |
); |
||
| 176 |
} |
||
| 177 | |||
| 178 |
function test_donate_succeedsWithHook() public {
|
||
| 179 |
donateRouter.donate(key, 100, 200, new bytes(333)); |
||
| 180 |
assertEq(mockHooks.beforeDonateData(), new bytes(333)); |
||
| 181 |
assertEq(mockHooks.afterDonateData(), new bytes(333)); |
||
| 182 |
} |
||
| 183 | |||
| 184 |
function test_beforeDonate_invalidReturn() public {
|
||
| 185 |
mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef)); |
||
| 186 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 187 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 188 |
} |
||
| 189 | |||
| 190 |
function test_afterDonate_invalidReturn() public {
|
||
| 191 |
mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef)); |
||
| 192 |
vm.expectRevert(Hooks.InvalidHookResponse.selector); |
||
| 193 |
donateRouter.donate(key, 100, 200, ZERO_BYTES); |
||
| 194 |
} |
||
| 195 | |||
| 196 |
// hook validation |
||
| 197 |
function test_fuzz_validateHookPermissions_noHooks(uint160 addr) public view {
|
||
| 198 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 199 | |||
| 200 |
IHooks hookAddr = IHooks(address(preAddr)); |
||
| 201 |
Hooks.validateHookPermissions( |
||
| 202 |
hookAddr, |
||
| 203 |
Hooks.Permissions({
|
||
| 204 |
beforeInitialize: false, |
||
| 205 |
afterInitialize: false, |
||
| 206 |
beforeAddLiquidity: false, |
||
| 207 |
afterAddLiquidity: false, |
||
| 208 |
beforeRemoveLiquidity: false, |
||
| 209 |
afterRemoveLiquidity: false, |
||
| 210 |
beforeSwap: false, |
||
| 211 |
afterSwap: false, |
||
| 212 |
beforeDonate: false, |
||
| 213 |
afterDonate: false, |
||
| 214 |
beforeSwapReturnDelta: false, |
||
| 215 |
afterSwapReturnDelta: false, |
||
| 216 |
afterAddLiquidityReturnDelta: false, |
||
| 217 |
afterRemoveLiquidityReturnDelta: false |
||
| 218 |
}) |
||
| 219 |
); |
||
| 220 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 221 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 222 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 223 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 224 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 225 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 226 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 227 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 228 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 229 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 230 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 231 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 232 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 233 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 234 |
} |
||
| 235 | |||
| 236 |
function test_fuzz_validateHookPermissions_beforeInitialize(uint160 addr) public view {
|
||
| 237 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 238 | |||
| 239 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_INITIALIZE_FLAG))); |
||
| 240 |
Hooks.validateHookPermissions( |
||
| 241 |
hookAddr, |
||
| 242 |
Hooks.Permissions({
|
||
| 243 |
beforeInitialize: true, |
||
| 244 |
afterInitialize: false, |
||
| 245 |
beforeAddLiquidity: false, |
||
| 246 |
afterAddLiquidity: false, |
||
| 247 |
beforeRemoveLiquidity: false, |
||
| 248 |
afterRemoveLiquidity: false, |
||
| 249 |
beforeSwap: false, |
||
| 250 |
afterSwap: false, |
||
| 251 |
beforeDonate: false, |
||
| 252 |
afterDonate: false, |
||
| 253 |
beforeSwapReturnDelta: false, |
||
| 254 |
afterSwapReturnDelta: false, |
||
| 255 |
afterAddLiquidityReturnDelta: false, |
||
| 256 |
afterRemoveLiquidityReturnDelta: false |
||
| 257 |
}) |
||
| 258 |
); |
||
| 259 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 260 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 261 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 262 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 263 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 264 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 265 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 266 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 267 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 268 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 269 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 270 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 271 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 272 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 273 |
} |
||
| 274 | |||
| 275 |
function test_fuzz_validateHookPermissions_afterInitialize(uint160 addr) public view {
|
||
| 276 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 277 | |||
| 278 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_INITIALIZE_FLAG))); |
||
| 279 |
Hooks.validateHookPermissions( |
||
| 280 |
hookAddr, |
||
| 281 |
Hooks.Permissions({
|
||
| 282 |
beforeInitialize: false, |
||
| 283 |
afterInitialize: true, |
||
| 284 |
beforeAddLiquidity: false, |
||
| 285 |
afterAddLiquidity: false, |
||
| 286 |
beforeRemoveLiquidity: false, |
||
| 287 |
afterRemoveLiquidity: false, |
||
| 288 |
beforeSwap: false, |
||
| 289 |
afterSwap: false, |
||
| 290 |
beforeDonate: false, |
||
| 291 |
afterDonate: false, |
||
| 292 |
beforeSwapReturnDelta: false, |
||
| 293 |
afterSwapReturnDelta: false, |
||
| 294 |
afterAddLiquidityReturnDelta: false, |
||
| 295 |
afterRemoveLiquidityReturnDelta: false |
||
| 296 |
}) |
||
| 297 |
); |
||
| 298 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 299 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 300 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 301 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 302 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 303 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 304 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 305 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 306 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 307 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 308 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 309 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 310 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 311 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 312 |
} |
||
| 313 | |||
| 314 |
function test_fuzz_validateHookPermissions_beforeAndAfterInitialize(uint160 addr) public view {
|
||
| 315 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 316 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG))); |
||
| 317 |
Hooks.validateHookPermissions( |
||
| 318 |
hookAddr, |
||
| 319 |
Hooks.Permissions({
|
||
| 320 |
beforeInitialize: true, |
||
| 321 |
afterInitialize: true, |
||
| 322 |
beforeAddLiquidity: false, |
||
| 323 |
afterAddLiquidity: false, |
||
| 324 |
beforeRemoveLiquidity: false, |
||
| 325 |
afterRemoveLiquidity: false, |
||
| 326 |
beforeSwap: false, |
||
| 327 |
afterSwap: false, |
||
| 328 |
beforeDonate: false, |
||
| 329 |
afterDonate: false, |
||
| 330 |
beforeSwapReturnDelta: false, |
||
| 331 |
afterSwapReturnDelta: false, |
||
| 332 |
afterAddLiquidityReturnDelta: false, |
||
| 333 |
afterRemoveLiquidityReturnDelta: false |
||
| 334 |
}) |
||
| 335 |
); |
||
| 336 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 337 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 338 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 339 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 340 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 341 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 342 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 343 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 344 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 345 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 346 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 347 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 348 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 349 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 350 |
} |
||
| 351 | |||
| 352 |
function test_fuzz_validateHookPermissions_beforeAddLiquidity(uint160 addr) public view {
|
||
| 353 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 354 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_ADD_LIQUIDITY_FLAG))); |
||
| 355 |
Hooks.validateHookPermissions( |
||
| 356 |
hookAddr, |
||
| 357 |
Hooks.Permissions({
|
||
| 358 |
beforeInitialize: false, |
||
| 359 |
afterInitialize: false, |
||
| 360 |
beforeAddLiquidity: true, |
||
| 361 |
afterAddLiquidity: false, |
||
| 362 |
beforeRemoveLiquidity: false, |
||
| 363 |
afterRemoveLiquidity: false, |
||
| 364 |
beforeSwap: false, |
||
| 365 |
afterSwap: false, |
||
| 366 |
beforeDonate: false, |
||
| 367 |
afterDonate: false, |
||
| 368 |
beforeSwapReturnDelta: false, |
||
| 369 |
afterSwapReturnDelta: false, |
||
| 370 |
afterAddLiquidityReturnDelta: false, |
||
| 371 |
afterRemoveLiquidityReturnDelta: false |
||
| 372 |
}) |
||
| 373 |
); |
||
| 374 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 375 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 376 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 377 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 378 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 379 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 380 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 381 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 382 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 383 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 384 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 385 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 386 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 387 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 388 |
} |
||
| 389 | |||
| 390 |
function test_fuzz_validateHookPermissions_afterAddLiquidity(uint160 addr) public view {
|
||
| 391 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 392 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_ADD_LIQUIDITY_FLAG))); |
||
| 393 |
Hooks.validateHookPermissions( |
||
| 394 |
hookAddr, |
||
| 395 |
Hooks.Permissions({
|
||
| 396 |
beforeInitialize: false, |
||
| 397 |
afterInitialize: false, |
||
| 398 |
beforeAddLiquidity: false, |
||
| 399 |
afterAddLiquidity: true, |
||
| 400 |
beforeRemoveLiquidity: false, |
||
| 401 |
afterRemoveLiquidity: false, |
||
| 402 |
beforeSwap: false, |
||
| 403 |
afterSwap: false, |
||
| 404 |
beforeDonate: false, |
||
| 405 |
afterDonate: false, |
||
| 406 |
beforeSwapReturnDelta: false, |
||
| 407 |
afterSwapReturnDelta: false, |
||
| 408 |
afterAddLiquidityReturnDelta: false, |
||
| 409 |
afterRemoveLiquidityReturnDelta: false |
||
| 410 |
}) |
||
| 411 |
); |
||
| 412 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 413 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 414 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 415 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 416 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 417 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 418 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 419 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 420 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 421 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 422 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 423 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 424 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 425 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 426 |
} |
||
| 427 | |||
| 428 |
function test_fuzz_validateHookPermissions_beforeAndAfterAddLiquidity(uint160 addr) public view {
|
||
| 429 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 430 |
IHooks hookAddr = |
||
| 431 |
IHooks(address(uint160(preAddr | Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG))); |
||
| 432 |
Hooks.validateHookPermissions( |
||
| 433 |
hookAddr, |
||
| 434 |
Hooks.Permissions({
|
||
| 435 |
beforeInitialize: false, |
||
| 436 |
afterInitialize: false, |
||
| 437 |
beforeAddLiquidity: true, |
||
| 438 |
afterAddLiquidity: true, |
||
| 439 |
beforeRemoveLiquidity: false, |
||
| 440 |
afterRemoveLiquidity: false, |
||
| 441 |
beforeSwap: false, |
||
| 442 |
afterSwap: false, |
||
| 443 |
beforeDonate: false, |
||
| 444 |
afterDonate: false, |
||
| 445 |
beforeSwapReturnDelta: false, |
||
| 446 |
afterSwapReturnDelta: false, |
||
| 447 |
afterAddLiquidityReturnDelta: false, |
||
| 448 |
afterRemoveLiquidityReturnDelta: false |
||
| 449 |
}) |
||
| 450 |
); |
||
| 451 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 452 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 453 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 454 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 455 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 456 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 457 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 458 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 459 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 460 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 461 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 462 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 463 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 464 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 465 |
} |
||
| 466 | |||
| 467 |
function test_fuzz_validateHookPermissions_beforeRemoveLiquidity(uint160 addr) public view {
|
||
| 468 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 469 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG))); |
||
| 470 |
Hooks.validateHookPermissions( |
||
| 471 |
hookAddr, |
||
| 472 |
Hooks.Permissions({
|
||
| 473 |
beforeInitialize: false, |
||
| 474 |
afterInitialize: false, |
||
| 475 |
beforeAddLiquidity: false, |
||
| 476 |
afterAddLiquidity: false, |
||
| 477 |
beforeRemoveLiquidity: true, |
||
| 478 |
afterRemoveLiquidity: false, |
||
| 479 |
beforeSwap: false, |
||
| 480 |
afterSwap: false, |
||
| 481 |
beforeDonate: false, |
||
| 482 |
afterDonate: false, |
||
| 483 |
beforeSwapReturnDelta: false, |
||
| 484 |
afterSwapReturnDelta: false, |
||
| 485 |
afterAddLiquidityReturnDelta: false, |
||
| 486 |
afterRemoveLiquidityReturnDelta: false |
||
| 487 |
}) |
||
| 488 |
); |
||
| 489 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 490 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 491 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 492 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 493 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 494 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 495 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 496 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 497 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 498 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 499 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 500 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 501 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 502 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 503 |
} |
||
| 504 | |||
| 505 |
function test_fuzz_validateHookPermissions_afterRemoveLiquidity(uint160 addr) public view {
|
||
| 506 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 507 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG))); |
||
| 508 |
Hooks.validateHookPermissions( |
||
| 509 |
hookAddr, |
||
| 510 |
Hooks.Permissions({
|
||
| 511 |
beforeInitialize: false, |
||
| 512 |
afterInitialize: false, |
||
| 513 |
beforeAddLiquidity: false, |
||
| 514 |
afterAddLiquidity: false, |
||
| 515 |
beforeRemoveLiquidity: false, |
||
| 516 |
afterRemoveLiquidity: true, |
||
| 517 |
beforeSwap: false, |
||
| 518 |
afterSwap: false, |
||
| 519 |
beforeDonate: false, |
||
| 520 |
afterDonate: false, |
||
| 521 |
beforeSwapReturnDelta: false, |
||
| 522 |
afterSwapReturnDelta: false, |
||
| 523 |
afterAddLiquidityReturnDelta: false, |
||
| 524 |
afterRemoveLiquidityReturnDelta: false |
||
| 525 |
}) |
||
| 526 |
); |
||
| 527 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 528 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 529 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 530 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 531 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 532 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 533 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 534 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 535 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 536 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 537 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 538 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 539 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 540 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 541 |
} |
||
| 542 | |||
| 543 |
function test_fuzz_validateHookPermissions_beforeAfterRemoveLiquidity(uint160 addr) public view {
|
||
| 544 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 545 |
IHooks hookAddr = |
||
| 546 |
IHooks(address(uint160(preAddr | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG))); |
||
| 547 |
Hooks.validateHookPermissions( |
||
| 548 |
hookAddr, |
||
| 549 |
Hooks.Permissions({
|
||
| 550 |
beforeInitialize: false, |
||
| 551 |
afterInitialize: false, |
||
| 552 |
beforeAddLiquidity: false, |
||
| 553 |
afterAddLiquidity: false, |
||
| 554 |
beforeRemoveLiquidity: true, |
||
| 555 |
afterRemoveLiquidity: true, |
||
| 556 |
beforeSwap: false, |
||
| 557 |
afterSwap: false, |
||
| 558 |
beforeDonate: false, |
||
| 559 |
afterDonate: false, |
||
| 560 |
beforeSwapReturnDelta: false, |
||
| 561 |
afterSwapReturnDelta: false, |
||
| 562 |
afterAddLiquidityReturnDelta: false, |
||
| 563 |
afterRemoveLiquidityReturnDelta: false |
||
| 564 |
}) |
||
| 565 |
); |
||
| 566 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 567 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 568 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 569 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 570 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 571 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 572 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 573 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 574 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 575 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 576 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 577 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 578 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 579 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 580 |
} |
||
| 581 | |||
| 582 |
function test_fuzz_validateHookPermissions_beforeInitializeAfterAddLiquidity(uint160 addr) public view {
|
||
| 583 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 584 |
IHooks hookAddr = |
||
| 585 |
IHooks(address(uint160(preAddr | Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG))); |
||
| 586 |
Hooks.validateHookPermissions( |
||
| 587 |
hookAddr, |
||
| 588 |
Hooks.Permissions({
|
||
| 589 |
beforeInitialize: true, |
||
| 590 |
afterInitialize: false, |
||
| 591 |
beforeAddLiquidity: false, |
||
| 592 |
afterAddLiquidity: true, |
||
| 593 |
beforeRemoveLiquidity: false, |
||
| 594 |
afterRemoveLiquidity: false, |
||
| 595 |
beforeSwap: false, |
||
| 596 |
afterSwap: false, |
||
| 597 |
beforeDonate: false, |
||
| 598 |
afterDonate: false, |
||
| 599 |
beforeSwapReturnDelta: false, |
||
| 600 |
afterSwapReturnDelta: false, |
||
| 601 |
afterAddLiquidityReturnDelta: false, |
||
| 602 |
afterRemoveLiquidityReturnDelta: false |
||
| 603 |
}) |
||
| 604 |
); |
||
| 605 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 606 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 607 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 608 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 609 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 610 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 611 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 612 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 613 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 614 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 615 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 616 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 617 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 618 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 619 |
} |
||
| 620 | |||
| 621 |
function test_fuzz_validateHookPermissions_beforeSwap(uint160 addr) public view {
|
||
| 622 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 623 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_SWAP_FLAG))); |
||
| 624 |
Hooks.validateHookPermissions( |
||
| 625 |
hookAddr, |
||
| 626 |
Hooks.Permissions({
|
||
| 627 |
beforeInitialize: false, |
||
| 628 |
afterInitialize: false, |
||
| 629 |
beforeAddLiquidity: false, |
||
| 630 |
afterAddLiquidity: false, |
||
| 631 |
beforeRemoveLiquidity: false, |
||
| 632 |
afterRemoveLiquidity: false, |
||
| 633 |
beforeSwap: true, |
||
| 634 |
afterSwap: false, |
||
| 635 |
beforeDonate: false, |
||
| 636 |
afterDonate: false, |
||
| 637 |
beforeSwapReturnDelta: false, |
||
| 638 |
afterSwapReturnDelta: false, |
||
| 639 |
afterAddLiquidityReturnDelta: false, |
||
| 640 |
afterRemoveLiquidityReturnDelta: false |
||
| 641 |
}) |
||
| 642 |
); |
||
| 643 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 644 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 645 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 646 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 647 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 648 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 649 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 650 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 651 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 652 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 653 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 654 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 655 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 656 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 657 |
} |
||
| 658 | |||
| 659 |
function test_fuzz_validateHookPermissions_afterSwap(uint160 addr) public view {
|
||
| 660 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 661 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_SWAP_FLAG))); |
||
| 662 |
Hooks.validateHookPermissions( |
||
| 663 |
hookAddr, |
||
| 664 |
Hooks.Permissions({
|
||
| 665 |
beforeInitialize: false, |
||
| 666 |
afterInitialize: false, |
||
| 667 |
beforeAddLiquidity: false, |
||
| 668 |
afterAddLiquidity: false, |
||
| 669 |
beforeRemoveLiquidity: false, |
||
| 670 |
afterRemoveLiquidity: false, |
||
| 671 |
beforeSwap: false, |
||
| 672 |
afterSwap: true, |
||
| 673 |
beforeDonate: false, |
||
| 674 |
afterDonate: false, |
||
| 675 |
beforeSwapReturnDelta: false, |
||
| 676 |
afterSwapReturnDelta: false, |
||
| 677 |
afterAddLiquidityReturnDelta: false, |
||
| 678 |
afterRemoveLiquidityReturnDelta: false |
||
| 679 |
}) |
||
| 680 |
); |
||
| 681 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 682 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 683 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 684 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 685 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 686 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 687 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 688 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 689 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 690 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 691 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 692 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 693 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 694 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 695 |
} |
||
| 696 | |||
| 697 |
function test_fuzz_validateHookPermissions_beforeAndAfterSwap(uint160 addr) public view {
|
||
| 698 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 699 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG))); |
||
| 700 |
Hooks.validateHookPermissions( |
||
| 701 |
hookAddr, |
||
| 702 |
Hooks.Permissions({
|
||
| 703 |
beforeInitialize: false, |
||
| 704 |
afterInitialize: false, |
||
| 705 |
beforeAddLiquidity: false, |
||
| 706 |
afterAddLiquidity: false, |
||
| 707 |
beforeRemoveLiquidity: false, |
||
| 708 |
afterRemoveLiquidity: false, |
||
| 709 |
beforeSwap: true, |
||
| 710 |
afterSwap: true, |
||
| 711 |
beforeDonate: false, |
||
| 712 |
afterDonate: false, |
||
| 713 |
beforeSwapReturnDelta: false, |
||
| 714 |
afterSwapReturnDelta: false, |
||
| 715 |
afterAddLiquidityReturnDelta: false, |
||
| 716 |
afterRemoveLiquidityReturnDelta: false |
||
| 717 |
}) |
||
| 718 |
); |
||
| 719 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 720 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 721 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 722 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 723 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 724 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 725 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 726 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 727 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 728 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 729 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 730 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 731 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 732 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 733 |
} |
||
| 734 | |||
| 735 |
function test_fuzz_validateHookPermissions_beforeDonate(uint160 addr) public view {
|
||
| 736 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 737 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_DONATE_FLAG))); |
||
| 738 |
Hooks.validateHookPermissions( |
||
| 739 |
hookAddr, |
||
| 740 |
Hooks.Permissions({
|
||
| 741 |
beforeInitialize: false, |
||
| 742 |
afterInitialize: false, |
||
| 743 |
beforeAddLiquidity: false, |
||
| 744 |
afterAddLiquidity: false, |
||
| 745 |
beforeRemoveLiquidity: false, |
||
| 746 |
afterRemoveLiquidity: false, |
||
| 747 |
beforeSwap: false, |
||
| 748 |
afterSwap: false, |
||
| 749 |
beforeDonate: true, |
||
| 750 |
afterDonate: false, |
||
| 751 |
beforeSwapReturnDelta: false, |
||
| 752 |
afterSwapReturnDelta: false, |
||
| 753 |
afterAddLiquidityReturnDelta: false, |
||
| 754 |
afterRemoveLiquidityReturnDelta: false |
||
| 755 |
}) |
||
| 756 |
); |
||
| 757 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 758 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 759 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 760 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 761 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 762 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 763 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 764 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 765 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 766 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 767 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 768 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 769 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 770 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 771 |
} |
||
| 772 | |||
| 773 |
function test_fuzz_validateHookPermissions_afterDonate(uint160 addr) public view {
|
||
| 774 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 775 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_DONATE_FLAG))); |
||
| 776 |
Hooks.validateHookPermissions( |
||
| 777 |
hookAddr, |
||
| 778 |
Hooks.Permissions({
|
||
| 779 |
beforeInitialize: false, |
||
| 780 |
afterInitialize: false, |
||
| 781 |
beforeAddLiquidity: false, |
||
| 782 |
afterAddLiquidity: false, |
||
| 783 |
beforeRemoveLiquidity: false, |
||
| 784 |
afterRemoveLiquidity: false, |
||
| 785 |
beforeSwap: false, |
||
| 786 |
afterSwap: false, |
||
| 787 |
beforeDonate: false, |
||
| 788 |
afterDonate: true, |
||
| 789 |
beforeSwapReturnDelta: false, |
||
| 790 |
afterSwapReturnDelta: false, |
||
| 791 |
afterAddLiquidityReturnDelta: false, |
||
| 792 |
afterRemoveLiquidityReturnDelta: false |
||
| 793 |
}) |
||
| 794 |
); |
||
| 795 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 796 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 797 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 798 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 799 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 800 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 801 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 802 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 803 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 804 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 805 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 806 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 807 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 808 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 809 |
} |
||
| 810 | |||
| 811 |
function test_fuzz_validateHookPermissions_beforeAndAfterDonate(uint160 addr) public view {
|
||
| 812 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 813 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_DONATE_FLAG | Hooks.AFTER_DONATE_FLAG))); |
||
| 814 |
Hooks.validateHookPermissions( |
||
| 815 |
hookAddr, |
||
| 816 |
Hooks.Permissions({
|
||
| 817 |
beforeInitialize: false, |
||
| 818 |
afterInitialize: false, |
||
| 819 |
beforeAddLiquidity: false, |
||
| 820 |
afterAddLiquidity: false, |
||
| 821 |
beforeRemoveLiquidity: false, |
||
| 822 |
afterRemoveLiquidity: false, |
||
| 823 |
beforeSwap: false, |
||
| 824 |
afterSwap: false, |
||
| 825 |
beforeDonate: true, |
||
| 826 |
afterDonate: true, |
||
| 827 |
beforeSwapReturnDelta: false, |
||
| 828 |
afterSwapReturnDelta: false, |
||
| 829 |
afterAddLiquidityReturnDelta: false, |
||
| 830 |
afterRemoveLiquidityReturnDelta: false |
||
| 831 |
}) |
||
| 832 |
); |
||
| 833 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 834 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 835 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 836 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 837 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 838 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 839 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 840 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 841 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 842 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 843 |
assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 844 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 845 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 846 |
assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 847 |
} |
||
| 848 | |||
| 849 |
function test_fuzz_validateHookPermissions_allHooks(uint160 addr) public view {
|
||
| 850 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 851 |
uint160 allHookBitsFlipped = uint160((1 << hookPermissionCount) - 1); |
||
| 852 |
IHooks hookAddr = IHooks(address(uint160(preAddr) | allHookBitsFlipped)); |
||
| 853 |
Hooks.validateHookPermissions( |
||
| 854 |
hookAddr, |
||
| 855 |
Hooks.Permissions({
|
||
| 856 |
beforeInitialize: true, |
||
| 857 |
afterInitialize: true, |
||
| 858 |
beforeAddLiquidity: true, |
||
| 859 |
afterAddLiquidity: true, |
||
| 860 |
beforeRemoveLiquidity: true, |
||
| 861 |
afterRemoveLiquidity: true, |
||
| 862 |
beforeSwap: true, |
||
| 863 |
afterSwap: true, |
||
| 864 |
beforeDonate: true, |
||
| 865 |
afterDonate: true, |
||
| 866 |
beforeSwapReturnDelta: true, |
||
| 867 |
afterSwapReturnDelta: true, |
||
| 868 |
afterAddLiquidityReturnDelta: true, |
||
| 869 |
afterRemoveLiquidityReturnDelta: true |
||
| 870 |
}) |
||
| 871 |
); |
||
| 872 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG)); |
||
| 873 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG)); |
||
| 874 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)); |
||
| 875 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG)); |
||
| 876 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)); |
||
| 877 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); |
||
| 878 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG)); |
||
| 879 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG)); |
||
| 880 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG)); |
||
| 881 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG)); |
||
| 882 |
assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)); |
||
| 883 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)); |
||
| 884 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 885 |
assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)); |
||
| 886 |
} |
||
| 887 | |||
| 888 |
function test_fuzz_validateHookAddress_failsAllHooks(uint160 addr, uint16 mask) public {
|
||
| 889 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 890 |
// Set the upper `hooksPermissionCount` number of bits to get the full mask in uint16. |
||
| 891 |
uint16 allHooksMask = uint16(~uint16(0)); |
||
| 892 |
// We want any combination except all hooks. |
||
| 893 |
vm.assume(mask < (allHooksMask >> (16 - hookPermissionCount))); |
||
| 894 |
IHooks hookAddr = IHooks(address(uint160(preAddr) | uint160(mask))); |
||
| 895 |
vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, (address(hookAddr)))); |
||
| 896 |
Hooks.validateHookPermissions( |
||
| 897 |
hookAddr, |
||
| 898 |
Hooks.Permissions({
|
||
| 899 |
beforeInitialize: true, |
||
| 900 |
afterInitialize: true, |
||
| 901 |
beforeAddLiquidity: true, |
||
| 902 |
afterAddLiquidity: true, |
||
| 903 |
beforeRemoveLiquidity: true, |
||
| 904 |
afterRemoveLiquidity: true, |
||
| 905 |
beforeSwap: true, |
||
| 906 |
afterSwap: true, |
||
| 907 |
beforeDonate: true, |
||
| 908 |
afterDonate: true, |
||
| 909 |
beforeSwapReturnDelta: true, |
||
| 910 |
afterSwapReturnDelta: true, |
||
| 911 |
afterAddLiquidityReturnDelta: true, |
||
| 912 |
afterRemoveLiquidityReturnDelta: true |
||
| 913 |
}) |
||
| 914 |
); |
||
| 915 |
} |
||
| 916 | |||
| 917 |
function test_fuzz_validateHookAddress_failsNoHooks(uint160 addr, uint16 mask) public {
|
||
| 918 |
// we only want hookPermissionCount of mask |
||
| 919 |
mask = mask >> (16 - hookPermissionCount); |
||
| 920 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 921 |
// We want any combination except no hooks. |
||
| 922 |
vm.assume(mask != 0); |
||
| 923 |
IHooks hookAddr = IHooks(address(preAddr | uint160(mask))); |
||
| 924 |
vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, (address(hookAddr)))); |
||
| 925 |
Hooks.validateHookPermissions( |
||
| 926 |
hookAddr, |
||
| 927 |
Hooks.Permissions({
|
||
| 928 |
beforeInitialize: false, |
||
| 929 |
afterInitialize: false, |
||
| 930 |
beforeAddLiquidity: false, |
||
| 931 |
afterAddLiquidity: false, |
||
| 932 |
beforeRemoveLiquidity: false, |
||
| 933 |
afterRemoveLiquidity: false, |
||
| 934 |
beforeSwap: false, |
||
| 935 |
afterSwap: false, |
||
| 936 |
beforeDonate: false, |
||
| 937 |
afterDonate: false, |
||
| 938 |
beforeSwapReturnDelta: false, |
||
| 939 |
afterSwapReturnDelta: false, |
||
| 940 |
afterAddLiquidityReturnDelta: false, |
||
| 941 |
afterRemoveLiquidityReturnDelta: false |
||
| 942 |
}) |
||
| 943 |
); |
||
| 944 |
} |
||
| 945 | |||
| 946 |
function test_isValidHookAddress_valid_anyFlags() public pure {
|
||
| 947 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000002000), 3000)); |
||
| 948 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000001000), 3000)); |
||
| 949 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000800), 3000)); |
||
| 950 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000400), 3000)); |
||
| 951 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000200), 3000)); |
||
| 952 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000100), 3000)); |
||
| 953 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000080), 3000)); |
||
| 954 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000040), 3000)); |
||
| 955 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000020), 3000)); |
||
| 956 |
assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000010), 3000)); |
||
| 957 |
assertTrue(Hooks.isValidHookAddress(IHooks(0xF00040A85D5Af5BF1d1762f925BdAddc42013C00), 3000)); |
||
| 958 |
} |
||
| 959 | |||
| 960 |
function test_isValidHookAddress_zeroAddress_fixedFee() public pure {
|
||
| 961 |
assertTrue(Hooks.isValidHookAddress(IHooks(address(0)), 3000)); |
||
| 962 |
} |
||
| 963 | |||
| 964 |
function testIsValidHookAddress_invalid_zeroAddressWithDynamicFee() public pure {
|
||
| 965 |
assertFalse(Hooks.isValidHookAddress(IHooks(address(0)), LPFeeLibrary.DYNAMIC_FEE_FLAG)); |
||
| 966 |
} |
||
| 967 | |||
| 968 |
function test_fuzz_isValidHookAddress_invalid_returnsDeltaWithoutHookFlag(uint160 addr) public view {
|
||
| 969 |
uint160 preAddr = addr & clearAllHookPermissionsMask; |
||
| 970 |
IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG))); |
||
| 971 |
assertFalse(Hooks.isValidHookAddress(hookAddr, 3000)); |
||
| 972 |
hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG))); |
||
| 973 |
assertFalse(Hooks.isValidHookAddress(hookAddr, 3000)); |
||
| 974 |
hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG))); |
||
| 975 |
assertFalse(Hooks.isValidHookAddress(hookAddr, 3000)); |
||
| 976 |
hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG))); |
||
| 977 |
assertFalse(Hooks.isValidHookAddress(hookAddr, 3000)); |
||
| 978 |
} |
||
| 979 | |||
| 980 |
function test_isValidHookAddress_valid_noFlagsWithDynamicFee() public pure {
|
||
| 981 |
assertTrue( |
||
| 982 |
Hooks.isValidHookAddress(IHooks(0x1000000000000000000000000000000000000000), LPFeeLibrary.DYNAMIC_FEE_FLAG) |
||
| 983 |
); |
||
| 984 |
} |
||
| 985 | |||
| 986 |
function test_isValidHookAddress_invalid_noFlagsNoDynamicFee() public pure {
|
||
| 987 |
assertFalse(Hooks.isValidHookAddress(IHooks(0x1000000000000000000000000000000000000000), 3000)); |
||
| 988 |
assertFalse(Hooks.isValidHookAddress(IHooks(0x0001000000000000000000000000000000004000), 3000)); |
||
| 989 |
assertFalse(Hooks.isValidHookAddress(IHooks(0x003840A85D5AF5bf1D1762F925BDaDdc42010000), 3000)); |
||
| 990 |
// not dynamic as another bit is dirty in the fee |
||
| 991 |
assertFalse( |
||
| 992 |
Hooks.isValidHookAddress( |
||
| 993 |
IHooks(0x1000000000000000000000000000000000000000), LPFeeLibrary.DYNAMIC_FEE_FLAG | uint24(3000) |
||
| 994 |
) |
||
| 995 |
); |
||
| 996 |
} |
||
| 997 | |||
| 998 |
function test_callHook_revertsWithBubbleUp() public {
|
||
| 999 |
// This test executes _callHook through beforeSwap. |
||
| 1000 |
address beforeSwapFlag = address(uint160(Hooks.BEFORE_SWAP_FLAG)); |
||
| 1001 |
vm.etch(beforeSwapFlag, address(revertingHookImpl).code); |
||
| 1002 |
BaseTestHooks revertingHook = BaseTestHooks(beforeSwapFlag); |
||
| 1003 | |||
| 1004 |
PoolKey memory key = PoolKey(currency0, currency1, 0, 60, IHooks(revertingHook)); |
||
| 1005 |
manager.initialize(key, SQRT_PRICE_1_1, new bytes(0)); |
||
| 1006 | |||
| 1007 |
IPoolManager.SwapParams memory swapParams = |
||
| 1008 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 1009 | |||
| 1010 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 1011 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 1012 | |||
| 1013 |
vm.expectRevert( |
||
| 1014 |
abi.encodeWithSelector( |
||
| 1015 |
Hooks.FailedHookCall.selector, abi.encodeWithSelector(BaseTestHooks.HookNotImplemented.selector) |
||
| 1016 |
) |
||
| 1017 |
); |
||
| 1018 |
swapRouter.swap(key, swapParams, testSettings, new bytes(0)); |
||
| 1019 |
} |
||
| 1020 | |||
| 1021 |
function test_callHook_revertsWithInternalErrorFailedHookCall() public {
|
||
| 1022 |
// This test executes _callHook through beforeSwap. |
||
| 1023 |
EmptyRevertContract emptyRevertingHookImpl = new EmptyRevertContract(); |
||
| 1024 |
address beforeSwapFlag = address(uint160(Hooks.BEFORE_SWAP_FLAG)); |
||
| 1025 |
vm.etch(beforeSwapFlag, address(emptyRevertingHookImpl).code); |
||
| 1026 |
EmptyRevertContract revertingHook = EmptyRevertContract(beforeSwapFlag); |
||
| 1027 | |||
| 1028 |
PoolKey memory key = PoolKey(currency0, currency1, 0, 60, IHooks(address(revertingHook))); |
||
| 1029 |
manager.initialize(key, SQRT_PRICE_1_1, new bytes(0)); |
||
| 1030 | |||
| 1031 |
IPoolManager.SwapParams memory swapParams = |
||
| 1032 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 1033 | |||
| 1034 |
PoolSwapTest.TestSettings memory testSettings = |
||
| 1035 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 1036 | |||
| 1037 |
vm.expectRevert(abi.encodeWithSelector(Hooks.FailedHookCall.selector, new bytes(0))); |
||
| 1038 |
swapRouter.swap(key, swapParams, testSettings, new bytes(0)); |
||
| 1039 |
} |
||
| 1040 |
} |
||
| 1041 |
| Lines covered: | 0 / 37 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import "../../src/libraries/LPFeeLibrary.sol"; |
||
| 5 |
import "forge-std/Test.sol"; |
||
| 6 | |||
| 7 |
contract LPFeeLibraryTest is Test {
|
||
| 8 |
function test_isDynamicFee_returnsTrue() public pure {
|
||
| 9 |
uint24 dynamicFee = 0x800000; |
||
| 10 |
assertTrue(LPFeeLibrary.isDynamicFee(dynamicFee)); |
||
| 11 |
} |
||
| 12 | |||
| 13 |
function test_isDynamicFee_returnsFalse_forOtherValues() public pure {
|
||
| 14 |
uint24 dynamicFee = 0xFFFFFF; |
||
| 15 |
assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee)); |
||
| 16 |
dynamicFee = 0x7FFFFF; |
||
| 17 |
assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee)); |
||
| 18 |
dynamicFee = 0; |
||
| 19 |
assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee)); |
||
| 20 |
dynamicFee = 0x800001; |
||
| 21 |
assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee)); |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function test_fuzz_isDynamicFee(uint24 fee) public pure {
|
||
| 25 |
assertEq(fee == LPFeeLibrary.DYNAMIC_FEE_FLAG, LPFeeLibrary.isDynamicFee(fee)); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function test_validate_doesNotRevertWithNoFee() public pure {
|
||
| 29 |
uint24 fee = 0; |
||
| 30 |
LPFeeLibrary.validate(fee); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function test_validate_doesNotRevert() public pure {
|
||
| 34 |
uint24 fee = 500000; // 50% |
||
| 35 |
LPFeeLibrary.validate(fee); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function test_validate_doesNotRevertWithMaxFee() public pure {
|
||
| 39 |
uint24 maxFee = 1000000; // 100% |
||
| 40 |
LPFeeLibrary.validate(maxFee); |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_validate_revertsWithLPFeeTooLarge() public {
|
||
| 44 |
uint24 fee = 1000001; |
||
| 45 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee)); |
||
| 46 |
LPFeeLibrary.validate(fee); |
||
| 47 |
} |
||
| 48 | |||
| 49 |
function test_fuzz_validate(uint24 fee) public {
|
||
| 50 |
if (fee > 1000000) {
|
||
| 51 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee)); |
||
| 52 |
} |
||
| 53 |
LPFeeLibrary.validate(fee); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function test_getInitialLPFee_forStaticFeeIsCorrect() public pure {
|
||
| 57 |
uint24 staticFee = 3000; // 30 bps |
||
| 58 |
assertEq(LPFeeLibrary.getInitialLPFee(staticFee), staticFee); |
||
| 59 |
} |
||
| 60 | |||
| 61 |
function test_getInitialLPFee_revertsWithLPFeeTooLarge_forStaticFee() public {
|
||
| 62 |
uint24 staticFee = 1000001; |
||
| 63 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, staticFee)); |
||
| 64 |
LPFeeLibrary.getInitialLPFee(staticFee); |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function test_getInitialLPFee_forDynamicFeeIsZero() public pure {
|
||
| 68 |
uint24 dynamicFee = 0x800000; |
||
| 69 |
assertEq(LPFeeLibrary.getInitialLPFee(dynamicFee), 0); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function test_getInitialLpFee_revertsWithNonExactDynamicFee() public {
|
||
| 73 |
uint24 dynamicFee = 0x800001; |
||
| 74 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, dynamicFee)); |
||
| 75 |
LPFeeLibrary.getInitialLPFee(dynamicFee); |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function test_fuzz_getInitialLPFee(uint24 fee) public {
|
||
| 79 |
if (fee == LPFeeLibrary.DYNAMIC_FEE_FLAG) {
|
||
| 80 |
assertEq(LPFeeLibrary.getInitialLPFee(fee), 0); |
||
| 81 |
} else if (fee > 1000000) {
|
||
| 82 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee)); |
||
| 83 |
LPFeeLibrary.getInitialLPFee(fee); |
||
| 84 |
} else {
|
||
| 85 |
assertEq(LPFeeLibrary.getInitialLPFee(fee), fee); |
||
| 86 |
} |
||
| 87 |
} |
||
| 88 |
} |
||
| 89 |
| Lines covered: | 0 / 23 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {SafeCast} from "src/libraries/SafeCast.sol";
|
||
| 6 |
import {LiquidityMathTest as LiquidityMath} from "src/test/LiquidityMathTest.sol";
|
||
| 7 | |||
| 8 |
contract LiquidityMathRef {
|
||
| 9 |
function addDelta(uint128 x, int128 y) external pure returns (uint128) {
|
||
| 10 |
return y < 0 ? x - uint128(-y) : x + uint128(y); |
||
| 11 |
} |
||
| 12 |
} |
||
| 13 | |||
| 14 |
contract LiquidityMathTest is Test {
|
||
| 15 |
LiquidityMath internal liquidityMath; |
||
| 16 |
LiquidityMathRef internal liquidityMathRef; |
||
| 17 | |||
| 18 |
function setUp() public {
|
||
| 19 |
liquidityMath = new LiquidityMath(); |
||
| 20 |
liquidityMathRef = new LiquidityMathRef(); |
||
| 21 |
} |
||
| 22 | |||
| 23 |
/// @notice Test the revert reason for underflow |
||
| 24 |
function test_addDelta_throwsForUnderflow() public {
|
||
| 25 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 26 |
liquidityMath.addDelta(0, -1); |
||
| 27 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 28 |
liquidityMath.addDelta(uint128(type(int128).max), type(int128).min); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
/// @notice Test the revert reason for overflow |
||
| 32 |
function test_addDelta_throwsForOverflow() public {
|
||
| 33 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 34 |
liquidityMath.addDelta(type(uint128).max, 1); |
||
| 35 |
} |
||
| 36 | |||
| 37 |
function test_addDelta_sub_int128min_throwsForReferenceOnly() public {
|
||
| 38 |
assertEq(liquidityMath.addDelta(uint128(type(int128).min), type(int128).min), 0); |
||
| 39 |
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
|
||
| 40 |
liquidityMathRef.addDelta(uint128(type(int128).min), type(int128).min); |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_addDelta_sub_int128min_fuzz(uint128 x) public view {
|
||
| 44 |
x = uint128(bound(x, uint128(type(int128).min), type(uint128).max)); |
||
| 45 |
assertEq(liquidityMath.addDelta(x, type(int128).min), x - uint128(type(int128).min)); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
/// @notice Test the equivalence of the new `addDelta` and the reference implementation |
||
| 49 |
function test_addDelta_fuzz(uint128 x, int128 y) public {
|
||
| 50 |
vm.assume(y != type(int128).min); |
||
| 51 |
try liquidityMath.addDelta(x, y) returns (uint128 z) {
|
||
| 52 |
assertEq(z, liquidityMathRef.addDelta(x, y)); |
||
| 53 |
} catch (bytes memory reason) {
|
||
| 54 |
assertEq(bytes4(reason), SafeCast.SafeCastOverflow.selector); |
||
| 55 |
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
|
||
| 56 |
liquidityMathRef.addDelta(x, y); |
||
| 57 |
} |
||
| 58 |
} |
||
| 59 |
} |
||
| 60 |
| Lines covered: | 0 / 7 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Lock} from "../../src/libraries/Lock.sol";
|
||
| 6 | |||
| 7 |
contract LockTest is Test {
|
||
| 8 |
function test_lock() public {
|
||
| 9 |
assertFalse(Lock.isUnlocked()); |
||
| 10 | |||
| 11 |
Lock.unlock(); |
||
| 12 | |||
| 13 |
assertTrue(Lock.isUnlocked()); |
||
| 14 | |||
| 15 |
Lock.lock(); |
||
| 16 | |||
| 17 |
assertFalse(Lock.isUnlocked()); |
||
| 18 |
} |
||
| 19 | |||
| 20 |
function test_unlockedSlot() public pure {
|
||
| 21 |
assertEq(bytes32(uint256(keccak256("Unlocked")) - 1), Lock.IS_UNLOCKED_SLOT);
|
||
| 22 |
} |
||
| 23 |
} |
||
| 24 |
| Lines covered: | 0 / 19 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {NonZeroDeltaCount} from "../../src/libraries/NonZeroDeltaCount.sol";
|
||
| 6 | |||
| 7 |
contract NonZeroDeltaCountTest is Test {
|
||
| 8 |
function test_incrementNonzeroDeltaCount() public {
|
||
| 9 |
assertEq(NonZeroDeltaCount.read(), 0); |
||
| 10 |
NonZeroDeltaCount.increment(); |
||
| 11 |
assertEq(NonZeroDeltaCount.read(), 1); |
||
| 12 |
} |
||
| 13 | |||
| 14 |
function test_decrementNonzeroDeltaCount() public {
|
||
| 15 |
assertEq(NonZeroDeltaCount.read(), 0); |
||
| 16 |
NonZeroDeltaCount.increment(); |
||
| 17 |
assertEq(NonZeroDeltaCount.read(), 1); |
||
| 18 |
NonZeroDeltaCount.decrement(); |
||
| 19 |
assertEq(NonZeroDeltaCount.read(), 0); |
||
| 20 |
} |
||
| 21 | |||
| 22 |
// Reading from right to left. Bit of 0: call increase. Bit of 1: call decrease. |
||
| 23 |
// The library allows over over/underflow so we dont check for that here |
||
| 24 |
function test_fuzz_nonZeroDeltaCount(uint256 instructions) public {
|
||
| 25 |
assertEq(NonZeroDeltaCount.read(), 0); |
||
| 26 |
uint256 expectedCount; |
||
| 27 |
for (uint256 i = 0; i < 256; i++) {
|
||
| 28 |
if ((instructions & (1 << i)) == 0) {
|
||
| 29 |
NonZeroDeltaCount.increment(); |
||
| 30 |
unchecked {
|
||
| 31 |
expectedCount++; |
||
| 32 |
} |
||
| 33 |
} else {
|
||
| 34 |
NonZeroDeltaCount.decrement(); |
||
| 35 |
unchecked {
|
||
| 36 |
expectedCount--; |
||
| 37 |
} |
||
| 38 |
} |
||
| 39 |
assertEq(NonZeroDeltaCount.read(), expectedCount); |
||
| 40 |
} |
||
| 41 |
} |
||
| 42 | |||
| 43 |
function test_nonZeroDeltaCountSlot() public pure {
|
||
| 44 |
assertEq(bytes32(uint256(keccak256("NonzeroDeltaCount")) - 1), NonZeroDeltaCount.NONZERO_DELTA_COUNT_SLOT);
|
||
| 45 |
} |
||
| 46 |
} |
||
| 47 |
| Lines covered: | 0 / 85 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {Pool} from "../../src/libraries/Pool.sol";
|
||
| 7 |
import {PoolManager} from "../../src/PoolManager.sol";
|
||
| 8 |
import {Position} from "../../src/libraries/Position.sol";
|
||
| 9 |
import {TickMath} from "../../src/libraries/TickMath.sol";
|
||
| 10 |
import {TickBitmap} from "../../src/libraries/TickBitmap.sol";
|
||
| 11 |
import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol";
|
||
| 12 |
import {Constants} from "../../test/utils/Constants.sol";
|
||
| 13 |
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
|
||
| 14 |
import {Slot0} from "../../src/types/Slot0.sol";
|
||
| 15 |
import {SafeCast} from "../../src/libraries/SafeCast.sol";
|
||
| 16 |
import {ProtocolFeeLibrary} from "../../src/libraries/ProtocolFeeLibrary.sol";
|
||
| 17 |
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
|
||
| 18 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 19 | |||
| 20 |
contract PoolTest is Test, GasSnapshot {
|
||
| 21 |
using Pool for Pool.State; |
||
| 22 |
using LPFeeLibrary for uint24; |
||
| 23 |
using ProtocolFeeLibrary for *; |
||
| 24 | |||
| 25 |
Pool.State state; |
||
| 26 | |||
| 27 |
uint24 constant MAX_PROTOCOL_FEE = ProtocolFeeLibrary.MAX_PROTOCOL_FEE; // 0.1% |
||
| 28 |
uint24 constant MAX_LP_FEE = LPFeeLibrary.MAX_LP_FEE; // 100% |
||
| 29 | |||
| 30 |
function testPoolInitialize(uint160 sqrtPriceX96, uint24 protocolFee, uint24 swapFee) public {
|
||
| 31 |
if (sqrtPriceX96 < TickMath.MIN_SQRT_PRICE || sqrtPriceX96 >= TickMath.MAX_SQRT_PRICE) {
|
||
| 32 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96)); |
||
| 33 |
state.initialize(sqrtPriceX96, protocolFee, swapFee); |
||
| 34 |
} else {
|
||
| 35 |
state.initialize(sqrtPriceX96, protocolFee, swapFee); |
||
| 36 |
assertEq(state.slot0.sqrtPriceX96(), sqrtPriceX96); |
||
| 37 |
assertEq(state.slot0.protocolFee(), protocolFee); |
||
| 38 |
assertEq(state.slot0.tick(), TickMath.getTickAtSqrtPrice(sqrtPriceX96)); |
||
| 39 |
assertLt(state.slot0.tick(), TickMath.MAX_TICK); |
||
| 40 |
assertGt(state.slot0.tick(), TickMath.MIN_TICK - 1); |
||
| 41 |
} |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function testModifyLiquidity( |
||
| 45 |
uint160 sqrtPriceX96, |
||
| 46 |
uint24 protocolFee, |
||
| 47 |
uint24 lpFee, |
||
| 48 |
Pool.ModifyLiquidityParams memory params |
||
| 49 |
) public {
|
||
| 50 |
// Assumptions tested in PoolManager.t.sol |
||
| 51 |
params.tickSpacing = int24(bound(params.tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); |
||
| 52 | |||
| 53 |
testPoolInitialize(sqrtPriceX96, protocolFee, lpFee); |
||
| 54 | |||
| 55 |
if (params.tickLower >= params.tickUpper) {
|
||
| 56 |
vm.expectRevert(abi.encodeWithSelector(Pool.TicksMisordered.selector, params.tickLower, params.tickUpper)); |
||
| 57 |
} else if (params.tickLower < TickMath.MIN_TICK) {
|
||
| 58 |
vm.expectRevert(abi.encodeWithSelector(Pool.TickLowerOutOfBounds.selector, params.tickLower)); |
||
| 59 |
} else if (params.tickUpper > TickMath.MAX_TICK) {
|
||
| 60 |
vm.expectRevert(abi.encodeWithSelector(Pool.TickUpperOutOfBounds.selector, params.tickUpper)); |
||
| 61 |
} else if (params.liquidityDelta < 0) {
|
||
| 62 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 63 |
} else if (params.liquidityDelta == 0) {
|
||
| 64 |
vm.expectRevert(Position.CannotUpdateEmptyPosition.selector); |
||
| 65 |
} else if (params.liquidityDelta > int128(Pool.tickSpacingToMaxLiquidityPerTick(params.tickSpacing))) {
|
||
| 66 |
vm.expectRevert(abi.encodeWithSelector(Pool.TickLiquidityOverflow.selector, params.tickLower)); |
||
| 67 |
} else if (params.tickLower % params.tickSpacing != 0) {
|
||
| 68 |
vm.expectRevert( |
||
| 69 |
abi.encodeWithSelector(TickBitmap.TickMisaligned.selector, params.tickLower, params.tickSpacing) |
||
| 70 |
); |
||
| 71 |
} else if (params.tickUpper % params.tickSpacing != 0) {
|
||
| 72 |
vm.expectRevert( |
||
| 73 |
abi.encodeWithSelector(TickBitmap.TickMisaligned.selector, params.tickUpper, params.tickSpacing) |
||
| 74 |
); |
||
| 75 |
} else {
|
||
| 76 |
// We need the assumptions above to calculate this |
||
| 77 |
uint256 maxInt128InTypeU256 = uint256(uint128(Constants.MAX_UINT128)); |
||
| 78 |
(uint256 amount0, uint256 amount1) = LiquidityAmounts.getAmountsForLiquidity( |
||
| 79 |
sqrtPriceX96, |
||
| 80 |
TickMath.getSqrtPriceAtTick(params.tickLower), |
||
| 81 |
TickMath.getSqrtPriceAtTick(params.tickUpper), |
||
| 82 |
uint128(params.liquidityDelta) |
||
| 83 |
); |
||
| 84 | |||
| 85 |
if ((amount0 > maxInt128InTypeU256) || (amount1 > maxInt128InTypeU256)) {
|
||
| 86 |
vm.expectRevert(abi.encodeWithSelector(SafeCast.SafeCastOverflow.selector)); |
||
| 87 |
} |
||
| 88 |
} |
||
| 89 | |||
| 90 |
params.owner = address(this); |
||
| 91 |
state.modifyLiquidity(params); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function test_fuzz_swap( |
||
| 95 |
uint160 sqrtPriceX96, |
||
| 96 |
uint24 lpFee, |
||
| 97 |
uint16 protocolFee0, |
||
| 98 |
uint16 protocolFee1, |
||
| 99 |
Pool.SwapParams memory params |
||
| 100 |
) public {
|
||
| 101 |
// Assumptions tested in PoolManager.t.sol |
||
| 102 |
params.tickSpacing = int24(bound(params.tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); |
||
| 103 |
lpFee = uint24(bound(lpFee, 0, MAX_LP_FEE)); |
||
| 104 |
protocolFee0 = uint16(bound(protocolFee0, 0, MAX_PROTOCOL_FEE)); |
||
| 105 |
protocolFee1 = uint16(bound(protocolFee1, 0, MAX_PROTOCOL_FEE)); |
||
| 106 |
uint24 protocolFee = protocolFee1 << 12 | protocolFee0; |
||
| 107 | |||
| 108 |
// initialize and add liquidity |
||
| 109 |
testModifyLiquidity( |
||
| 110 |
sqrtPriceX96, |
||
| 111 |
protocolFee, |
||
| 112 |
lpFee, |
||
| 113 |
Pool.ModifyLiquidityParams({
|
||
| 114 |
owner: address(this), |
||
| 115 |
tickLower: -120, |
||
| 116 |
tickUpper: 120, |
||
| 117 |
liquidityDelta: 1e18, |
||
| 118 |
tickSpacing: 60, |
||
| 119 |
salt: 0 |
||
| 120 |
}) |
||
| 121 |
); |
||
| 122 |
Slot0 slot0 = state.slot0; |
||
| 123 | |||
| 124 |
uint24 _lpFee = params.lpFeeOverride.isOverride() ? params.lpFeeOverride.removeOverrideFlag() : lpFee; |
||
| 125 |
uint24 swapFee = protocolFee == 0 ? _lpFee : uint16(protocolFee).calculateSwapFee(_lpFee); |
||
| 126 | |||
| 127 |
if (params.amountSpecified >= 0 && swapFee == MAX_LP_FEE) {
|
||
| 128 |
vm.expectRevert(Pool.InvalidFeeForExactOut.selector); |
||
| 129 |
state.swap(params); |
||
| 130 |
} else if (!_lpFee.isValid()) {
|
||
| 131 |
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, _lpFee)); |
||
| 132 |
state.swap(params); |
||
| 133 |
} else if (params.zeroForOne && params.amountSpecified != 0) {
|
||
| 134 |
if (params.sqrtPriceLimitX96 >= slot0.sqrtPriceX96()) {
|
||
| 135 |
vm.expectRevert( |
||
| 136 |
abi.encodeWithSelector( |
||
| 137 |
Pool.PriceLimitAlreadyExceeded.selector, slot0.sqrtPriceX96(), params.sqrtPriceLimitX96 |
||
| 138 |
) |
||
| 139 |
); |
||
| 140 |
state.swap(params); |
||
| 141 |
} else if (params.sqrtPriceLimitX96 <= TickMath.MIN_SQRT_PRICE) {
|
||
| 142 |
vm.expectRevert(abi.encodeWithSelector(Pool.PriceLimitOutOfBounds.selector, params.sqrtPriceLimitX96)); |
||
| 143 |
state.swap(params); |
||
| 144 |
} |
||
| 145 |
} else if (!params.zeroForOne && params.amountSpecified != 0) {
|
||
| 146 |
if (params.sqrtPriceLimitX96 <= slot0.sqrtPriceX96()) {
|
||
| 147 |
vm.expectRevert( |
||
| 148 |
abi.encodeWithSelector( |
||
| 149 |
Pool.PriceLimitAlreadyExceeded.selector, slot0.sqrtPriceX96(), params.sqrtPriceLimitX96 |
||
| 150 |
) |
||
| 151 |
); |
||
| 152 |
state.swap(params); |
||
| 153 |
} else if (params.sqrtPriceLimitX96 >= TickMath.MAX_SQRT_PRICE) {
|
||
| 154 |
vm.expectRevert(abi.encodeWithSelector(Pool.PriceLimitOutOfBounds.selector, params.sqrtPriceLimitX96)); |
||
| 155 |
state.swap(params); |
||
| 156 |
} |
||
| 157 |
} else {
|
||
| 158 |
uint160 sqrtPriceBefore = state.slot0.sqrtPriceX96(); |
||
| 159 |
state.swap(params); |
||
| 160 | |||
| 161 |
if (params.amountSpecified == 0) {
|
||
| 162 |
assertEq(sqrtPriceBefore, state.slot0.sqrtPriceX96(), "amountSpecified == 0"); |
||
| 163 |
} else if (params.zeroForOne) {
|
||
| 164 |
assertGe(state.slot0.sqrtPriceX96(), params.sqrtPriceLimitX96, "zeroForOne"); |
||
| 165 |
} else {
|
||
| 166 |
assertLe(state.slot0.sqrtPriceX96(), params.sqrtPriceLimitX96, "oneForZero"); |
||
| 167 |
} |
||
| 168 |
} |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function test_fuzz_tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) public pure {
|
||
| 172 |
tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); |
||
| 173 |
// v3 math |
||
| 174 |
int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing; |
||
| 175 |
int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing; |
||
| 176 |
uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1; |
||
| 177 |
// assert that the result is the same as the v3 math |
||
| 178 |
assertEq(type(uint128).max / numTicks, Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing)); |
||
| 179 |
} |
||
| 180 |
} |
||
| 181 |
| Lines covered: | 0 / 4 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
|
||
| 6 |
import {PoolKey} from "../../src/types/PoolKey.sol";
|
||
| 7 | |||
| 8 |
contract PoolIdTest is Test {
|
||
| 9 |
using PoolIdLibrary for PoolKey; |
||
| 10 | |||
| 11 |
function test_fuzz_toId(PoolKey memory poolKey) public pure {
|
||
| 12 |
bytes memory encodedKey = abi.encode(poolKey); |
||
| 13 |
bytes32 expectedHash = keccak256(encodedKey); |
||
| 14 |
assertEq(PoolId.unwrap(poolKey.toId()), expectedHash, "hashes not equal"); |
||
| 15 |
} |
||
| 16 |
} |
||
| 17 |
| Lines covered: | 0 / 35 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Position} from "../../src/libraries/Position.sol";
|
||
| 6 |
import {SafeCast} from "../../src/libraries/SafeCast.sol";
|
||
| 7 | |||
| 8 |
contract PositionTest is Test {
|
||
| 9 |
using Position for mapping(bytes32 => Position.Info); |
||
| 10 | |||
| 11 |
mapping(bytes32 => Position.Info) internal positions; |
||
| 12 | |||
| 13 |
function test_fuzz_get(address owner, int24 tickLower, int24 tickUpper, bytes32 salt) public view {
|
||
| 14 |
bytes32 positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)); |
||
| 15 |
Position.Info storage expectedPosition = positions[positionKey]; |
||
| 16 |
Position.Info storage position = positions.get(owner, tickLower, tickUpper, salt); |
||
| 17 |
bytes32 expectedPositionSlot; |
||
| 18 |
bytes32 positionSlot; |
||
| 19 |
assembly ("memory-safe") {
|
||
| 20 |
expectedPositionSlot := expectedPosition.slot |
||
| 21 |
positionSlot := position.slot |
||
| 22 |
} |
||
| 23 |
assertEq(positionSlot, expectedPositionSlot, "slots not equal"); |
||
| 24 |
} |
||
| 25 | |||
| 26 |
function test_fuzz_update( |
||
| 27 |
int128 liquidityDelta, |
||
| 28 |
Position.Info memory pos, |
||
| 29 |
uint256 newFeeGrowthInside0X128, |
||
| 30 |
uint256 newFeeGrowthInside1X128 |
||
| 31 |
) public {
|
||
| 32 |
Position.Info storage position = positions[0]; |
||
| 33 |
position.liquidity = pos.liquidity; |
||
| 34 |
position.feeGrowthInside0LastX128 = pos.feeGrowthInside0LastX128; |
||
| 35 |
position.feeGrowthInside1LastX128 = pos.feeGrowthInside1LastX128; |
||
| 36 | |||
| 37 |
uint128 oldLiquidity = position.liquidity; |
||
| 38 | |||
| 39 |
if (position.liquidity == 0 && liquidityDelta == 0) {
|
||
| 40 |
vm.expectRevert(Position.CannotUpdateEmptyPosition.selector); |
||
| 41 |
} |
||
| 42 | |||
| 43 |
// new liquidity cannot overflow/underflow uint128 |
||
| 44 |
uint256 absLiquidityDelta; |
||
| 45 |
if (liquidityDelta > 0) {
|
||
| 46 |
absLiquidityDelta = uint256(uint128(liquidityDelta)); |
||
| 47 |
uint256 newLiquidity = position.liquidity + absLiquidityDelta; |
||
| 48 |
if (newLiquidity > type(uint128).max) {
|
||
| 49 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 50 |
} |
||
| 51 |
} else if (liquidityDelta < 0) {
|
||
| 52 |
if (liquidityDelta == type(int128).min) {
|
||
| 53 |
absLiquidityDelta = uint256(uint128(type(int128).max)) + 1; |
||
| 54 |
} else {
|
||
| 55 |
absLiquidityDelta = uint256(uint128(-liquidityDelta)); |
||
| 56 |
} |
||
| 57 |
if (position.liquidity < absLiquidityDelta) {
|
||
| 58 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 59 |
} |
||
| 60 |
} |
||
| 61 | |||
| 62 |
Position.update(position, liquidityDelta, newFeeGrowthInside0X128, newFeeGrowthInside1X128); |
||
| 63 |
if (liquidityDelta == 0) {
|
||
| 64 |
assertEq(position.liquidity, oldLiquidity); |
||
| 65 |
} else if (liquidityDelta > 0) {
|
||
| 66 |
assertEq(position.liquidity, oldLiquidity + absLiquidityDelta); |
||
| 67 |
} else {
|
||
| 68 |
assertEq(position.liquidity, oldLiquidity - absLiquidityDelta); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
assertEq(position.feeGrowthInside0LastX128, newFeeGrowthInside0X128); |
||
| 72 |
assertEq(position.feeGrowthInside1LastX128, newFeeGrowthInside1X128); |
||
| 73 |
} |
||
| 74 |
} |
||
| 75 |
| Lines covered: | 0 / 36 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 6 |
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
|
||
| 7 |
import {ProtocolFeeLibrary} from "../../src/libraries/ProtocolFeeLibrary.sol";
|
||
| 8 | |||
| 9 |
contract ProtocolFeeLibraryTest is Test, GasSnapshot {
|
||
| 10 |
function test_getZeroForOneFee() public pure {
|
||
| 11 |
uint24 fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE; |
||
| 12 |
assertEq(ProtocolFeeLibrary.getZeroForOneFee(fee), uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE)); |
||
| 13 |
} |
||
| 14 | |||
| 15 |
function test_fuzz_getZeroForOneFee(uint24 fee) public pure {
|
||
| 16 |
assertEq(ProtocolFeeLibrary.getZeroForOneFee(fee), fee % 4096); |
||
| 17 |
} |
||
| 18 | |||
| 19 |
function test_getOneForZeroFee() public pure {
|
||
| 20 |
uint24 fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE; |
||
| 21 |
assertEq(ProtocolFeeLibrary.getOneForZeroFee(fee), uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1)); |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function test_fuzz_getOneForZeroFee(uint24 fee) public pure {
|
||
| 25 |
assertEq(ProtocolFeeLibrary.getOneForZeroFee(fee), fee >> 12); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function test_isValidProtocolFee_fee() public pure {
|
||
| 29 |
uint24 fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE; |
||
| 30 |
assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 31 | |||
| 32 |
fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE) << 12 | (ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1); |
||
| 33 |
assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 34 | |||
| 35 |
fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1) << 12 | (ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1); |
||
| 36 |
assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 37 | |||
| 38 |
fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE; |
||
| 39 |
assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 40 | |||
| 41 |
fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1; |
||
| 42 |
assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 43 | |||
| 44 |
fee = uint24(0) << 12 | uint24(0); |
||
| 45 |
assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function test_fuzz_isValidProtocolFee(uint24 fee) public pure {
|
||
| 49 |
if ((fee >> 12 > ProtocolFeeLibrary.MAX_PROTOCOL_FEE) || (fee % 4096 > ProtocolFeeLibrary.MAX_PROTOCOL_FEE)) {
|
||
| 50 |
assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 51 |
} else {
|
||
| 52 |
assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee)); |
||
| 53 |
} |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function test_calculateSwapFee() public pure {
|
||
| 57 |
assertEq( |
||
| 58 |
ProtocolFeeLibrary.calculateSwapFee(uint16(ProtocolFeeLibrary.MAX_PROTOCOL_FEE), LPFeeLibrary.MAX_LP_FEE), |
||
| 59 |
LPFeeLibrary.MAX_LP_FEE |
||
| 60 |
); |
||
| 61 |
assertEq(ProtocolFeeLibrary.calculateSwapFee(uint16(ProtocolFeeLibrary.MAX_PROTOCOL_FEE), 3000), 3997); |
||
| 62 |
assertEq( |
||
| 63 |
ProtocolFeeLibrary.calculateSwapFee(uint16(ProtocolFeeLibrary.MAX_PROTOCOL_FEE), 0), |
||
| 64 |
ProtocolFeeLibrary.MAX_PROTOCOL_FEE |
||
| 65 |
); |
||
| 66 |
assertEq(ProtocolFeeLibrary.calculateSwapFee(0, 0), 0); |
||
| 67 |
assertEq(ProtocolFeeLibrary.calculateSwapFee(0, 1000), 1000); |
||
| 68 |
} |
||
| 69 | |||
| 70 |
function test_fuzz_calculateSwapFee(uint16 protocolFee, uint24 lpFee) public pure {
|
||
| 71 |
protocolFee = uint16(bound(protocolFee, 0, ProtocolFeeLibrary.MAX_PROTOCOL_FEE)); |
||
| 72 |
lpFee = uint24(bound(lpFee, 0, LPFeeLibrary.MAX_LP_FEE)); |
||
| 73 |
uint24 swapFee = ProtocolFeeLibrary.calculateSwapFee(protocolFee, lpFee); |
||
| 74 |
// if lp fee is not the max, the swap fee should never be the max since the protocol fee is taken off first and then the lp fee is taken from the remaining amount |
||
| 75 |
if (lpFee < LPFeeLibrary.MAX_LP_FEE) {
|
||
| 76 |
assertLt(swapFee, LPFeeLibrary.MAX_LP_FEE); |
||
| 77 |
} else {
|
||
| 78 |
// otherwise it is equal to max, and can therefore never be larger |
||
| 79 |
assertEq(swapFee, LPFeeLibrary.MAX_LP_FEE); |
||
| 80 |
} |
||
| 81 | |||
| 82 |
assertGe(swapFee, lpFee); |
||
| 83 | |||
| 84 |
uint256 expectedSwapFee = |
||
| 85 |
protocolFee + lpFee * uint256(LPFeeLibrary.MAX_LP_FEE - protocolFee) / LPFeeLibrary.MAX_LP_FEE; |
||
| 86 |
assertEq(swapFee, uint24(expectedSwapFee)); |
||
| 87 |
} |
||
| 88 |
} |
||
| 89 |
| Lines covered: | 0 / 44 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {SafeCast} from "../../src/libraries/SafeCast.sol";
|
||
| 7 | |||
| 8 |
contract SafeCastTest is Test {
|
||
| 9 |
function test_fuzz_toUint160(uint256 x) public {
|
||
| 10 |
if (x <= type(uint160).max) {
|
||
| 11 |
assertEq(uint256(SafeCast.toUint160(x)), x); |
||
| 12 |
} else {
|
||
| 13 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 14 |
SafeCast.toUint160(x); |
||
| 15 |
} |
||
| 16 |
} |
||
| 17 | |||
| 18 |
function test_toUint160() public {
|
||
| 19 |
assertEq(uint256(SafeCast.toUint160(0)), 0); |
||
| 20 |
assertEq(uint256(SafeCast.toUint160(type(uint160).max)), type(uint160).max); |
||
| 21 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 22 |
SafeCast.toUint160(type(uint160).max + uint256(1)); |
||
| 23 |
} |
||
| 24 | |||
| 25 |
function test_fuzz_toUint128(uint256 x) public {
|
||
| 26 |
if (x <= type(uint128).max) {
|
||
| 27 |
assertEq(uint256(SafeCast.toUint128(x)), x); |
||
| 28 |
} else {
|
||
| 29 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 30 |
SafeCast.toUint128(x); |
||
| 31 |
} |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function test_toUint128() public {
|
||
| 35 |
assertEq(uint256(SafeCast.toUint128(0)), 0); |
||
| 36 |
assertEq(uint256(SafeCast.toUint128(type(uint128).max)), type(uint128).max); |
||
| 37 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 38 |
SafeCast.toUint128(type(uint128).max + uint256(1)); |
||
| 39 |
} |
||
| 40 | |||
| 41 |
function test_fuzz_toInt128_fromInt256(int256 x) public {
|
||
| 42 |
if (x <= type(int128).max && x >= type(int128).min) {
|
||
| 43 |
assertEq(int256(SafeCast.toInt128(x)), x); |
||
| 44 |
} else {
|
||
| 45 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 46 |
SafeCast.toInt128(x); |
||
| 47 |
} |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function test_toInt128_fromInt256() public {
|
||
| 51 |
assertEq(int256(SafeCast.toInt128(int256(0))), 0); |
||
| 52 |
assertEq(int256(SafeCast.toInt128(type(int128).max)), type(int128).max); |
||
| 53 |
assertEq(int256(SafeCast.toInt128(type(int128).min)), type(int128).min); |
||
| 54 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 55 |
SafeCast.toInt128(type(int128).max + int256(1)); |
||
| 56 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 57 |
SafeCast.toInt128(type(int128).min - int256(1)); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function test_fuzz_toInt256(uint256 x) public {
|
||
| 61 |
if (x <= uint256(type(int256).max)) {
|
||
| 62 |
assertEq(uint256(SafeCast.toInt256(x)), x); |
||
| 63 |
} else {
|
||
| 64 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 65 |
SafeCast.toInt256(x); |
||
| 66 |
} |
||
| 67 |
} |
||
| 68 | |||
| 69 |
function test_toInt256() public {
|
||
| 70 |
assertEq(uint256(SafeCast.toInt256(0)), 0); |
||
| 71 |
assertEq(uint256(SafeCast.toInt256(uint256(type(int256).max))), uint256(type(int256).max)); |
||
| 72 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 73 |
SafeCast.toInt256(uint256(type(int256).max) + uint256(1)); |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function test_fuzz_toInt128_fromUint256(uint256 x) public {
|
||
| 77 |
if (x <= uint128(type(int128).max)) {
|
||
| 78 |
assertEq(uint128(SafeCast.toInt128(x)), x); |
||
| 79 |
} else {
|
||
| 80 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 81 |
SafeCast.toInt128(x); |
||
| 82 |
} |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function test_toInt128_fromUint256() public {
|
||
| 86 |
assertEq(uint128(SafeCast.toInt128(uint256(0))), 0); |
||
| 87 |
assertEq(uint128(SafeCast.toInt128(uint256(uint128(type(int128).max)))), uint128(type(int128).max)); |
||
| 88 |
vm.expectRevert(SafeCast.SafeCastOverflow.selector); |
||
| 89 |
SafeCast.toInt128(uint256(uint128(type(int128).max)) + uint256(1)); |
||
| 90 |
} |
||
| 91 |
} |
||
| 92 |
| Lines covered: | 0 / 132 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 7 |
import {SqrtPriceMath} from "../../src/libraries/SqrtPriceMath.sol";
|
||
| 8 |
import {Constants} from "../../test/utils/Constants.sol";
|
||
| 9 | |||
| 10 |
contract SqrtPriceMathTest is Test, GasSnapshot {
|
||
| 11 |
function test_getNextSqrtPriceFromInput_revertsIfPriceIsZero() public {
|
||
| 12 |
vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector); |
||
| 13 |
SqrtPriceMath.getNextSqrtPriceFromInput(0, 1, 0.1 ether, false); |
||
| 14 |
} |
||
| 15 | |||
| 16 |
function test_getNextSqrtPriceFromInput_revertsIfLiquidityIsZero() public {
|
||
| 17 |
vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector); |
||
| 18 |
SqrtPriceMath.getNextSqrtPriceFromInput(1, 0, 0.1 ether, true); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function test_getNextSqrtPriceFromInput_revertsIfInputAmountOverflowsThePrice() public {
|
||
| 22 |
uint160 price = Constants.MAX_UINT160 - 1; |
||
| 23 |
uint128 liquidity = 1024; |
||
| 24 |
uint256 amountIn = 1024; |
||
| 25 | |||
| 26 |
vm.expectRevert(); |
||
| 27 |
SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, amountIn, false); |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function test_getNextSqrtPriceFromInput_anyInputAmountCannotUnderflowThePrice() public pure {
|
||
| 31 |
uint160 price = 1; |
||
| 32 |
uint128 liquidity = 1; |
||
| 33 |
uint256 amountIn = 2 ** 255; |
||
| 34 | |||
| 35 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, amountIn, true); |
||
| 36 | |||
| 37 |
assertEq(sqrtQ, 1); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function test_getNextSqrtPriceFromInput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsTrue() public pure {
|
||
| 41 |
uint160 price = Constants.SQRT_PRICE_1_1; |
||
| 42 |
uint128 liquidity = 1; |
||
| 43 | |||
| 44 |
assertEq(SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, 0, true), price); |
||
| 45 |
} |
||
| 46 | |||
| 47 |
function test_getNextSqrtPriceFromInput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsFalse() public pure {
|
||
| 48 |
uint160 price = Constants.SQRT_PRICE_1_1; |
||
| 49 |
uint128 liquidity = 1; |
||
| 50 | |||
| 51 |
assertEq(SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, 0, false), price); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
function test_getNextSqrtPriceFromInput_returnsTheMinimumPriceForMaxInputs() public pure {
|
||
| 55 |
uint160 sqrtP = Constants.MAX_UINT160 - 1; |
||
| 56 |
uint128 liquidity = Constants.MAX_UINT128; |
||
| 57 |
uint256 maxAmountNoOverflow = Constants.MAX_UINT256 - Constants.MAX_UINT128 << 96 / sqrtP; |
||
| 58 | |||
| 59 |
assertEq(SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, liquidity, maxAmountNoOverflow, true), 1); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function test_getNextSqrtPriceFromInput_inputAmountOf0_1Currency1() public pure {
|
||
| 63 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 64 | |||
| 65 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, false); |
||
| 66 | |||
| 67 |
assertEq(sqrtQ, Constants.SQRT_PRICE_121_100); |
||
| 68 |
} |
||
| 69 | |||
| 70 |
function test_getNextSqrtPriceFromInput_inputAmountOf0_1Currency0() public pure {
|
||
| 71 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 72 | |||
| 73 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, true); |
||
| 74 | |||
| 75 |
assertEq(sqrtQ, 72025602285694852357767227579); |
||
| 76 |
} |
||
| 77 | |||
| 78 |
function test_getNextSqrtPriceFromInput_amountInGreaterThanType_uint96_maxAndZeroForOneEqualsTrue() public pure {
|
||
| 79 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 80 | |||
| 81 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(10 ether), 2 ** 100, true); |
||
| 82 | |||
| 83 |
// perfect answer: |
||
| 84 |
// https://www.wolframalpha.com/input/?i=624999999995069620+-+%28%281e19+*+1+%2F+%281e19+%2B+2%5E100+*+1%29%29+*+2%5E96%29 |
||
| 85 |
assertEq(sqrtQ, 624999999995069620); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function test_getNextSqrtPriceFromInput_canReturn1WithEnoughAmountInAndZeroForOneEqualsTrue() public pure {
|
||
| 89 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 90 | |||
| 91 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, 1, Constants.MAX_UINT256 / 2, true); |
||
| 92 | |||
| 93 |
assertEq(sqrtQ, 1); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
// |
||
| 97 |
function test_getNextSqrtPriceFromInput_zeroForOneEqualsTrueGas() public {
|
||
| 98 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 99 | |||
| 100 |
snapStart("getNextSqrtPriceFromInput_zeroForOneEqualsTrueGas");
|
||
| 101 |
SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, true); |
||
| 102 |
snapEnd(); |
||
| 103 |
} |
||
| 104 | |||
| 105 |
function test_getNextSqrtPriceFromInput_zeroForOneEqualsFalseGas() public {
|
||
| 106 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 107 | |||
| 108 |
snapStart("getNextSqrtPriceFromInput_zeroForOneEqualsFalseGas");
|
||
| 109 |
SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, false); |
||
| 110 |
snapEnd(); |
||
| 111 |
} |
||
| 112 | |||
| 113 |
function test_getNextSqrtPriceFromOutput_revertsIfPriceIsZero() public {
|
||
| 114 |
vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector); |
||
| 115 |
SqrtPriceMath.getNextSqrtPriceFromOutput(0, 1, 0.1 ether, false); |
||
| 116 |
} |
||
| 117 | |||
| 118 |
function test_getNextSqrtPriceFromOutput_revertsIfLiquidityIsZero() public {
|
||
| 119 |
vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector); |
||
| 120 |
SqrtPriceMath.getNextSqrtPriceFromOutput(1, 0, 0.1 ether, true); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsExactlyTheVirtualReservesOfCurrency0() public {
|
||
| 124 |
uint160 price = 20282409603651670423947251286016; |
||
| 125 |
uint128 liquidity = 1024; |
||
| 126 |
uint256 amountOut = 4; |
||
| 127 | |||
| 128 |
vm.expectRevert(SqrtPriceMath.PriceOverflow.selector); |
||
| 129 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, false); |
||
| 130 |
} |
||
| 131 | |||
| 132 |
function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsGreaterThanTheVirtualReservesOfCurrency0() public {
|
||
| 133 |
uint160 price = 20282409603651670423947251286016; |
||
| 134 |
uint128 liquidity = 1024; |
||
| 135 |
uint256 amountOut = 5; |
||
| 136 | |||
| 137 |
vm.expectRevert(SqrtPriceMath.PriceOverflow.selector); |
||
| 138 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, false); |
||
| 139 |
} |
||
| 140 | |||
| 141 |
function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsGreaterThanTheVirtualReservesOfCurrency1() public {
|
||
| 142 |
uint160 price = 20282409603651670423947251286016; |
||
| 143 |
uint128 liquidity = 1024; |
||
| 144 |
uint256 amountOut = 262145; |
||
| 145 | |||
| 146 |
vm.expectRevert(SqrtPriceMath.NotEnoughLiquidity.selector); |
||
| 147 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, true); |
||
| 148 |
} |
||
| 149 | |||
| 150 |
function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsExactlyTheVirtualReservesOfCurrency1() public {
|
||
| 151 |
uint160 price = 20282409603651670423947251286016; |
||
| 152 |
uint128 liquidity = 1024; |
||
| 153 |
uint256 amountOut = 262144; |
||
| 154 | |||
| 155 |
vm.expectRevert(SqrtPriceMath.NotEnoughLiquidity.selector); |
||
| 156 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, true); |
||
| 157 |
} |
||
| 158 | |||
| 159 |
function test_getNextSqrtPriceFromOutput_succeedsIfOutputAmountIsJustLessThanTheVirtualReservesOfCurrency1() |
||
| 160 |
public |
||
| 161 |
pure |
||
| 162 |
{
|
||
| 163 |
uint160 price = 20282409603651670423947251286016; |
||
| 164 |
uint128 liquidity = 1024; |
||
| 165 |
uint256 amountOut = 262143; |
||
| 166 | |||
| 167 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, true); |
||
| 168 | |||
| 169 |
assertEq(sqrtQ, 77371252455336267181195264); |
||
| 170 |
} |
||
| 171 | |||
| 172 |
function test_getNextSqrtPriceFromOutput_puzzlingEchidnaTest() public {
|
||
| 173 |
uint160 price = 20282409603651670423947251286016; |
||
| 174 |
uint128 liquidity = 1024; |
||
| 175 |
uint256 amountOut = 4; |
||
| 176 | |||
| 177 |
vm.expectRevert(SqrtPriceMath.PriceOverflow.selector); |
||
| 178 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, false); |
||
| 179 |
} |
||
| 180 | |||
| 181 |
function test_getNextSqrtPriceFromOutput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsTrue() public pure {
|
||
| 182 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 183 | |||
| 184 |
uint256 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(0.1 ether), 0, true); |
||
| 185 | |||
| 186 |
assertEq(sqrtP, sqrtQ); |
||
| 187 |
} |
||
| 188 | |||
| 189 |
function test_getNextSqrtPriceFromOutput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsFalse() public pure {
|
||
| 190 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 191 | |||
| 192 |
uint256 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(0.1 ether), 0, false); |
||
| 193 | |||
| 194 |
assertEq(sqrtP, sqrtQ); |
||
| 195 |
} |
||
| 196 | |||
| 197 |
function test_getNextSqrtPriceFromOutput_outputAmountOf0_1Currency1() public pure {
|
||
| 198 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 199 | |||
| 200 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, false); |
||
| 201 | |||
| 202 |
assertEq(sqrtQ, 88031291682515930659493278152); |
||
| 203 |
} |
||
| 204 | |||
| 205 |
function test_getNextSqrtPriceFromOutput_outputAmountOf0_1Currency0() public pure {
|
||
| 206 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 207 | |||
| 208 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, true); |
||
| 209 | |||
| 210 |
assertEq(sqrtQ, 71305346262837903834189555302); |
||
| 211 |
} |
||
| 212 | |||
| 213 |
function test_getNextSqrtPriceFromOutput_revertsIfAmountOutIsImpossibleInZeroForOneDirection() public {
|
||
| 214 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 215 | |||
| 216 |
vm.expectRevert(); |
||
| 217 |
SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, 1, Constants.MAX_UINT256, true); |
||
| 218 |
} |
||
| 219 | |||
| 220 |
function test_getNextSqrtPriceFromOutput_revertsIfAmountOutIsImpossibleInOneForZeroDirection() public {
|
||
| 221 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 222 | |||
| 223 |
vm.expectRevert(SqrtPriceMath.PriceOverflow.selector); |
||
| 224 |
SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, 1, Constants.MAX_UINT256, false); |
||
| 225 |
} |
||
| 226 | |||
| 227 |
function test_getNextSqrtPriceFromOutput_zeroForOneEqualsTrueGas() public {
|
||
| 228 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 229 | |||
| 230 |
snapStart("getNextSqrtPriceFromOutput_zeroForOneEqualsTrueGas");
|
||
| 231 |
SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, true); |
||
| 232 |
snapEnd(); |
||
| 233 |
} |
||
| 234 | |||
| 235 |
function test_getNextSqrtPriceFromOutput_zeroForOneEqualsFalseGas() public {
|
||
| 236 |
uint160 sqrtP = Constants.SQRT_PRICE_1_1; |
||
| 237 | |||
| 238 |
snapStart("getNextSqrtPriceFromOutput_zeroForOneEqualsFalseGas");
|
||
| 239 |
SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, false); |
||
| 240 |
snapEnd(); |
||
| 241 |
} |
||
| 242 | |||
| 243 |
function test_getAmount0Delta_returns0IfLiquidityIs0() public pure {
|
||
| 244 |
uint256 amount0 = SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_2_1, 0, true); |
||
| 245 | |||
| 246 |
assertEq(amount0, 0); |
||
| 247 |
} |
||
| 248 | |||
| 249 |
function test_getAmount0Delta_returns0IfPricesAreEqual() public pure {
|
||
| 250 |
uint256 amount0 = SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_1_1, 0, true); |
||
| 251 | |||
| 252 |
assertEq(amount0, 0); |
||
| 253 |
} |
||
| 254 | |||
| 255 |
function test_getAmount0Delta_revertsIfPriceIsZero() public {
|
||
| 256 |
vm.expectRevert(SqrtPriceMath.InvalidPrice.selector); |
||
| 257 |
SqrtPriceMath.getAmount0Delta(0, 1, 1, true); |
||
| 258 |
} |
||
| 259 | |||
| 260 |
function test_getAmount0Delta_1Amount1ForPriceOf1To1_21() public pure {
|
||
| 261 |
uint256 amount0 = SqrtPriceMath.getAmount0Delta( |
||
| 262 |
Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), true |
||
| 263 |
); |
||
| 264 | |||
| 265 |
assertEq(amount0, 90909090909090910); |
||
| 266 | |||
| 267 |
uint256 amount0RoundedDown = SqrtPriceMath.getAmount0Delta( |
||
| 268 |
Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), false |
||
| 269 |
); |
||
| 270 | |||
| 271 |
assertEq(amount0RoundedDown, amount0 - 1); |
||
| 272 |
} |
||
| 273 | |||
| 274 |
function test_getAmount0Delta_worksForPricesThatOverflow() public pure {
|
||
| 275 |
// sqrtP_1 = encodeSqrtPriceX96(2^90, 1) |
||
| 276 |
uint160 sqrtP_1 = 2787593149816327892691964784081045188247552; |
||
| 277 |
// sqrtP_2 = encodeSqrtPriceX96(2^96, 1) |
||
| 278 |
uint160 sqrtP_2 = 22300745198530623141535718272648361505980416; |
||
| 279 | |||
| 280 |
uint256 amount0Up = SqrtPriceMath.getAmount0Delta(sqrtP_1, sqrtP_2, uint128(1 ether), true); |
||
| 281 | |||
| 282 |
uint256 amount0Down = SqrtPriceMath.getAmount0Delta(sqrtP_1, sqrtP_2, uint128(1 ether), false); |
||
| 283 | |||
| 284 |
assertEq(amount0Up, amount0Down + 1); |
||
| 285 |
} |
||
| 286 | |||
| 287 |
function test_getAmount0Delta_gasCostForAmount0WhereRoundUpIsTrue() public {
|
||
| 288 |
snapStart("getAmount0Delta_gasCostForAmount0WhereRoundUpIsTrue");
|
||
| 289 |
SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), true); |
||
| 290 |
snapEnd(); |
||
| 291 |
} |
||
| 292 | |||
| 293 |
function test_getAmount0Delta_gasCostForAmount0WhereRoundUpIsFalse() public {
|
||
| 294 |
snapStart("getAmount0Delta_gasCostForAmount0WhereRoundUpIsFalse");
|
||
| 295 |
SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), false); |
||
| 296 |
snapEnd(); |
||
| 297 |
} |
||
| 298 | |||
| 299 |
function test_getAmount1Delta_returns0IfLiquidityIs0() public pure {
|
||
| 300 |
uint256 amount1 = SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_2_1, 0, true); |
||
| 301 | |||
| 302 |
assertEq(amount1, 0); |
||
| 303 |
} |
||
| 304 | |||
| 305 |
function test_getAmount1Delta_returns0IfPricesAreEqual() public pure {
|
||
| 306 |
uint256 amount1 = SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_1_1, 0, true); |
||
| 307 | |||
| 308 |
assertEq(amount1, 0); |
||
| 309 |
} |
||
| 310 | |||
| 311 |
function test_getAmount1Delta_1Amount1ForPriceOf1To1_21() public pure {
|
||
| 312 |
uint256 amount1 = SqrtPriceMath.getAmount1Delta( |
||
| 313 |
Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), true |
||
| 314 |
); |
||
| 315 | |||
| 316 |
assertEq(amount1, 100000000000000000); |
||
| 317 | |||
| 318 |
uint256 amount1RoundedDown = SqrtPriceMath.getAmount1Delta( |
||
| 319 |
Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), false |
||
| 320 |
); |
||
| 321 | |||
| 322 |
assertEq(amount1RoundedDown, amount1 - 1); |
||
| 323 |
} |
||
| 324 | |||
| 325 |
function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue() public {
|
||
| 326 |
snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue");
|
||
| 327 |
SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), true); |
||
| 328 |
snapEnd(); |
||
| 329 |
} |
||
| 330 | |||
| 331 |
function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse() public {
|
||
| 332 |
snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse");
|
||
| 333 |
SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), false); |
||
| 334 |
snapEnd(); |
||
| 335 |
} |
||
| 336 | |||
| 337 |
function test_swapComputation_sqrtPTimessqrtQOverflows() public pure {
|
||
| 338 |
// getNextSqrtPriceInvariants(1025574284609383690408304870162715216695788925244,50015962439936049619261659728067971248,406,true) |
||
| 339 |
uint160 sqrtP = 1025574284609383690408304870162715216695788925244; |
||
| 340 |
uint128 liquidity = 50015962439936049619261659728067971248; |
||
| 341 |
bool zeroForOne = true; |
||
| 342 |
uint128 amountIn = 406; |
||
| 343 | |||
| 344 |
uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, liquidity, amountIn, zeroForOne); |
||
| 345 |
assertEq(sqrtQ, 1025574284609383582644711336373707553698163132913); |
||
| 346 | |||
| 347 |
uint256 amount0Delta = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, true); |
||
| 348 |
assertEq(amount0Delta, 406); |
||
| 349 |
} |
||
| 350 |
} |
||
| 351 |
| Lines covered: | 0 / 273 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.19; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 6 |
import {IHooks} from "../../src/interfaces/IHooks.sol";
|
||
| 7 |
import {Hooks} from "../../src/libraries/Hooks.sol";
|
||
| 8 |
import {TickMath} from "../../src/libraries/TickMath.sol";
|
||
| 9 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 10 |
import {PoolKey} from "../../src/types/PoolKey.sol";
|
||
| 11 |
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
|
||
| 12 |
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
|
||
| 13 |
import {CurrencyLibrary, Currency} from "../../src/types/Currency.sol";
|
||
| 14 |
import {Deployers} from "../utils/Deployers.sol";
|
||
| 15 |
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
|
||
| 16 |
import {Pool} from "../../src/libraries/Pool.sol";
|
||
| 17 |
import {TickBitmap} from "../../src/libraries/TickBitmap.sol";
|
||
| 18 |
import {FixedPoint128} from "../../src/libraries/FixedPoint128.sol";
|
||
| 19 | |||
| 20 |
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
|
||
| 21 |
import {Fuzzers} from "../../src/test/Fuzzers.sol";
|
||
| 22 | |||
| 23 |
contract StateLibraryTest is Test, Deployers, Fuzzers, GasSnapshot {
|
||
| 24 |
using FixedPointMathLib for uint256; |
||
| 25 |
using PoolIdLibrary for PoolKey; |
||
| 26 | |||
| 27 |
PoolId poolId; |
||
| 28 | |||
| 29 |
function setUp() public {
|
||
| 30 |
// creates the pool manager, utility routers, and test tokens |
||
| 31 |
Deployers.deployFreshManagerAndRouters(); |
||
| 32 |
(currency0, currency1) = Deployers.deployMintAndApprove2Currencies(); |
||
| 33 | |||
| 34 |
// Create the pool |
||
| 35 |
key = PoolKey(currency0, currency1, 3000, 60, IHooks(address(0x0))); |
||
| 36 |
poolId = key.toId(); |
||
| 37 |
manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function test_getSlot0() public {
|
||
| 41 |
// create liquidity |
||
| 42 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 43 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES |
||
| 44 |
); |
||
| 45 | |||
| 46 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 47 |
key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES |
||
| 48 |
); |
||
| 49 | |||
| 50 |
// swap to create fees, crossing a tick |
||
| 51 |
uint256 swapAmount = 100 ether; |
||
| 52 |
swap(key, true, -int256(swapAmount), ZERO_BYTES); |
||
| 53 |
(uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 swapFee) = StateLibrary.getSlot0(manager, poolId); |
||
| 54 |
snapLastCall("extsload getSlot0");
|
||
| 55 |
assertEq(tick, -139); |
||
| 56 | |||
| 57 |
// magic number verified against a native getter |
||
| 58 |
assertEq(sqrtPriceX96, 78680104762184586858280382455); |
||
| 59 |
assertEq(tick, -139); |
||
| 60 |
assertEq(protocolFee, 0); // tested in protocol fee tests |
||
| 61 |
assertEq(swapFee, 3000); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function test_getTickLiquidity() public {
|
||
| 65 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 10 ether, 0), ZERO_BYTES); |
||
| 66 | |||
| 67 |
(uint128 liquidityGrossLower, int128 liquidityNetLower) = StateLibrary.getTickLiquidity(manager, poolId, -60); |
||
| 68 |
snapLastCall("extsload getTickLiquidity");
|
||
| 69 |
assertEq(liquidityGrossLower, 10 ether); |
||
| 70 |
assertEq(liquidityNetLower, 10 ether); |
||
| 71 | |||
| 72 |
(uint128 liquidityGrossUpper, int128 liquidityNetUpper) = StateLibrary.getTickLiquidity(manager, poolId, 60); |
||
| 73 |
assertEq(liquidityGrossUpper, 10 ether); |
||
| 74 |
assertEq(liquidityNetUpper, -10 ether); |
||
| 75 |
} |
||
| 76 | |||
| 77 |
function test_fuzz_getTickLiquidity(IPoolManager.ModifyLiquidityParams memory params) public {
|
||
| 78 |
(IPoolManager.ModifyLiquidityParams memory _params,) = |
||
| 79 |
Fuzzers.createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 80 |
uint128 liquidityDelta = uint128(uint256(_params.liquidityDelta)); |
||
| 81 | |||
| 82 |
(uint128 liquidityGrossLower, int128 liquidityNetLower) = |
||
| 83 |
StateLibrary.getTickLiquidity(manager, poolId, _params.tickLower); |
||
| 84 |
assertEq(liquidityGrossLower, liquidityDelta); |
||
| 85 |
assertEq(liquidityNetLower, int128(_params.liquidityDelta)); |
||
| 86 | |||
| 87 |
(uint128 liquidityGrossUpper, int128 liquidityNetUpper) = |
||
| 88 |
StateLibrary.getTickLiquidity(manager, poolId, _params.tickUpper); |
||
| 89 |
assertEq(liquidityGrossUpper, liquidityDelta); |
||
| 90 |
assertEq(liquidityNetUpper, -int128(_params.liquidityDelta)); |
||
| 91 | |||
| 92 |
// confirm agreement with getTickInfo() |
||
| 93 |
(uint128 _liquidityGrossLower, int128 _liquidityNetLower,,) = |
||
| 94 |
StateLibrary.getTickInfo(manager, poolId, _params.tickLower); |
||
| 95 |
assertEq(_liquidityGrossLower, liquidityGrossLower); |
||
| 96 |
assertEq(_liquidityNetLower, liquidityNetLower); |
||
| 97 | |||
| 98 |
(uint128 _liquidityGrossUpper, int128 _liquidityNetUpper,,) = |
||
| 99 |
StateLibrary.getTickInfo(manager, poolId, _params.tickUpper); |
||
| 100 |
assertEq(_liquidityGrossUpper, liquidityGrossUpper); |
||
| 101 |
assertEq(_liquidityNetUpper, liquidityNetUpper); |
||
| 102 |
} |
||
| 103 | |||
| 104 |
function test_fuzz_getTickLiquidity_two_positions( |
||
| 105 |
IPoolManager.ModifyLiquidityParams memory paramsA, |
||
| 106 |
IPoolManager.ModifyLiquidityParams memory paramsB |
||
| 107 |
) public {
|
||
| 108 |
(IPoolManager.ModifyLiquidityParams memory _paramsA,) = Fuzzers.createFuzzyLiquidityWithTightBound( |
||
| 109 |
modifyLiquidityRouter, key, paramsA, SQRT_PRICE_1_1, ZERO_BYTES, 2 |
||
| 110 |
); |
||
| 111 |
(IPoolManager.ModifyLiquidityParams memory _paramsB,) = Fuzzers.createFuzzyLiquidityWithTightBound( |
||
| 112 |
modifyLiquidityRouter, key, paramsB, SQRT_PRICE_1_1, ZERO_BYTES, 2 |
||
| 113 |
); |
||
| 114 | |||
| 115 |
uint128 liquidityDeltaA = uint128(uint256(_paramsA.liquidityDelta)); |
||
| 116 |
uint128 liquidityDeltaB = uint128(uint256(_paramsB.liquidityDelta)); |
||
| 117 | |||
| 118 |
(uint128 liquidityGrossLowerA, int128 liquidityNetLowerA) = |
||
| 119 |
StateLibrary.getTickLiquidity(manager, poolId, _paramsA.tickLower); |
||
| 120 |
(uint128 liquidityGrossLowerB, int128 liquidityNetLowerB) = |
||
| 121 |
StateLibrary.getTickLiquidity(manager, poolId, _paramsB.tickLower); |
||
| 122 |
(uint256 liquidityGrossUpperA, int256 liquidityNetUpperA) = |
||
| 123 |
StateLibrary.getTickLiquidity(manager, poolId, _paramsA.tickUpper); |
||
| 124 |
(uint256 liquidityGrossUpperB, int256 liquidityNetUpperB) = |
||
| 125 |
StateLibrary.getTickLiquidity(manager, poolId, _paramsB.tickUpper); |
||
| 126 | |||
| 127 |
// when tick lower is shared between two positions, the gross liquidity is the sum |
||
| 128 |
if (_paramsA.tickLower == _paramsB.tickLower || _paramsA.tickLower == _paramsB.tickUpper) {
|
||
| 129 |
assertEq(liquidityGrossLowerA, liquidityDeltaA + liquidityDeltaB); |
||
| 130 | |||
| 131 |
// when tick lower is shared with an upper tick, the net liquidity is the difference |
||
| 132 |
(_paramsA.tickLower == _paramsB.tickLower) |
||
| 133 |
? assertEq(liquidityNetLowerA, int128(liquidityDeltaA + liquidityDeltaB)) |
||
| 134 |
: assertApproxEqAbs(liquidityNetLowerA, int128(liquidityDeltaA) - int128(liquidityDeltaB), 1 wei); |
||
| 135 |
} else {
|
||
| 136 |
assertEq(liquidityGrossLowerA, liquidityDeltaA); |
||
| 137 |
assertEq(liquidityNetLowerA, int128(liquidityDeltaA)); |
||
| 138 |
} |
||
| 139 | |||
| 140 |
if (_paramsA.tickUpper == _paramsB.tickLower || _paramsA.tickUpper == _paramsB.tickUpper) {
|
||
| 141 |
assertEq(liquidityGrossUpperA, liquidityDeltaA + liquidityDeltaB); |
||
| 142 |
(_paramsA.tickUpper == _paramsB.tickUpper) |
||
| 143 |
? assertEq(liquidityNetUpperA, -int128(liquidityDeltaA + liquidityDeltaB)) |
||
| 144 |
: assertApproxEqAbs(liquidityNetUpperA, int128(liquidityDeltaB) - int128(liquidityDeltaA), 2 wei); |
||
| 145 |
} else {
|
||
| 146 |
assertEq(liquidityGrossUpperA, liquidityDeltaA); |
||
| 147 |
assertEq(liquidityNetUpperA, -int128(liquidityDeltaA)); |
||
| 148 |
} |
||
| 149 | |||
| 150 |
if (_paramsB.tickLower == _paramsA.tickLower || _paramsB.tickLower == _paramsA.tickUpper) {
|
||
| 151 |
assertEq(liquidityGrossLowerB, liquidityDeltaA + liquidityDeltaB); |
||
| 152 |
(_paramsB.tickLower == _paramsA.tickLower) |
||
| 153 |
? assertEq(liquidityNetLowerB, int128(liquidityDeltaA + liquidityDeltaB)) |
||
| 154 |
: assertApproxEqAbs(liquidityNetLowerB, int128(liquidityDeltaB) - int128(liquidityDeltaA), 1 wei); |
||
| 155 |
} else {
|
||
| 156 |
assertEq(liquidityGrossLowerB, liquidityDeltaB); |
||
| 157 |
assertEq(liquidityNetLowerB, int128(liquidityDeltaB)); |
||
| 158 |
} |
||
| 159 | |||
| 160 |
if (_paramsB.tickUpper == _paramsA.tickLower || _paramsB.tickUpper == _paramsA.tickUpper) {
|
||
| 161 |
assertEq(liquidityGrossUpperB, liquidityDeltaA + liquidityDeltaB); |
||
| 162 |
(_paramsB.tickUpper == _paramsA.tickUpper) |
||
| 163 |
? assertEq(liquidityNetUpperB, -int128(liquidityDeltaA + liquidityDeltaB)) |
||
| 164 |
: assertApproxEqAbs(liquidityNetUpperB, int128(liquidityDeltaA) - int128(liquidityDeltaB), 2 wei); |
||
| 165 |
} else {
|
||
| 166 |
assertEq(liquidityGrossUpperB, liquidityDeltaB); |
||
| 167 |
assertEq(liquidityNetUpperB, -int128(liquidityDeltaB)); |
||
| 168 |
} |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function test_getFeeGrowthGlobals0() public {
|
||
| 172 |
// create liquidity |
||
| 173 |
uint256 liquidity = 10_000 ether; |
||
| 174 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 175 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, int256(liquidity), 0), ZERO_BYTES |
||
| 176 |
); |
||
| 177 | |||
| 178 |
(uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId); |
||
| 179 |
assertEq(feeGrowthGlobal0, 0); |
||
| 180 |
assertEq(feeGrowthGlobal1, 0); |
||
| 181 | |||
| 182 |
// swap to create fees on the input token (currency0) |
||
| 183 |
uint256 swapAmount = 10 ether; |
||
| 184 |
swap(key, true, -int256(swapAmount), ZERO_BYTES); |
||
| 185 | |||
| 186 |
(feeGrowthGlobal0, feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId); |
||
| 187 |
snapLastCall("extsload getFeeGrowthGlobals");
|
||
| 188 | |||
| 189 |
uint256 feeGrowthGlobalCalc = swapAmount.mulWadDown(0.003e18).mulDivDown(FixedPoint128.Q128, liquidity); |
||
| 190 |
assertEq(feeGrowthGlobal0, feeGrowthGlobalCalc); |
||
| 191 |
assertEq(feeGrowthGlobal1, 0); |
||
| 192 |
} |
||
| 193 | |||
| 194 |
function test_getFeeGrowthGlobals1() public {
|
||
| 195 |
// create liquidity |
||
| 196 |
uint256 liquidity = 10_000 ether; |
||
| 197 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 198 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, int256(liquidity), 0), ZERO_BYTES |
||
| 199 |
); |
||
| 200 | |||
| 201 |
(uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId); |
||
| 202 |
assertEq(feeGrowthGlobal0, 0); |
||
| 203 |
assertEq(feeGrowthGlobal1, 0); |
||
| 204 | |||
| 205 |
// swap to create fees on the input token (currency1) |
||
| 206 |
uint256 swapAmount = 10 ether; |
||
| 207 |
swap(key, false, -int256(swapAmount), ZERO_BYTES); |
||
| 208 | |||
| 209 |
(feeGrowthGlobal0, feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId); |
||
| 210 | |||
| 211 |
assertEq(feeGrowthGlobal0, 0); |
||
| 212 |
uint256 feeGrowthGlobalCalc = swapAmount.mulWadDown(0.003e18).mulDivDown(FixedPoint128.Q128, liquidity); |
||
| 213 |
assertEq(feeGrowthGlobal1, feeGrowthGlobalCalc); |
||
| 214 |
} |
||
| 215 | |||
| 216 |
function test_getLiquidity() public {
|
||
| 217 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 10 ether, 0), ZERO_BYTES); |
||
| 218 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 219 |
key, IPoolManager.ModifyLiquidityParams(-120, 120, 10 ether, 0), ZERO_BYTES |
||
| 220 |
); |
||
| 221 | |||
| 222 |
uint128 liquidity = StateLibrary.getLiquidity(manager, poolId); |
||
| 223 |
snapLastCall("extsload getLiquidity");
|
||
| 224 |
assertEq(liquidity, 20 ether); |
||
| 225 |
} |
||
| 226 | |||
| 227 |
function test_fuzz_getLiquidity(IPoolManager.ModifyLiquidityParams memory params) public {
|
||
| 228 |
(IPoolManager.ModifyLiquidityParams memory _params,) = |
||
| 229 |
Fuzzers.createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 230 |
(, int24 tick,,) = StateLibrary.getSlot0(manager, poolId); |
||
| 231 |
uint128 liquidity = StateLibrary.getLiquidity(manager, poolId); |
||
| 232 | |||
| 233 |
// out of range liquidity is not added to Pool.State.liquidity |
||
| 234 |
if (tick < _params.tickLower || tick >= _params.tickUpper) {
|
||
| 235 |
assertEq(liquidity, 0); |
||
| 236 |
} else {
|
||
| 237 |
assertEq(liquidity, uint128(uint256(_params.liquidityDelta))); |
||
| 238 |
} |
||
| 239 |
} |
||
| 240 | |||
| 241 |
function test_getTickBitmap() public {
|
||
| 242 |
int24 tickLower = -300; |
||
| 243 |
int24 tickUpper = 300; |
||
| 244 |
// create liquidity |
||
| 245 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 246 |
key, IPoolManager.ModifyLiquidityParams(tickLower, tickUpper, 10_000 ether, 0), ZERO_BYTES |
||
| 247 |
); |
||
| 248 | |||
| 249 |
(int16 wordPos, uint8 bitPos) = TickBitmap.position(tickLower / key.tickSpacing); |
||
| 250 |
uint256 tickBitmap = StateLibrary.getTickBitmap(manager, poolId, wordPos); |
||
| 251 |
snapLastCall("extsload getTickBitmap");
|
||
| 252 |
assertNotEq(tickBitmap, 0); |
||
| 253 |
assertEq(tickBitmap, 1 << bitPos); |
||
| 254 | |||
| 255 |
(wordPos, bitPos) = TickBitmap.position(tickUpper / key.tickSpacing); |
||
| 256 |
tickBitmap = StateLibrary.getTickBitmap(manager, poolId, wordPos); |
||
| 257 |
assertNotEq(tickBitmap, 0); |
||
| 258 |
assertEq(tickBitmap, 1 << bitPos); |
||
| 259 |
} |
||
| 260 | |||
| 261 |
function test_fuzz_getTickBitmap(IPoolManager.ModifyLiquidityParams memory params) public {
|
||
| 262 |
(IPoolManager.ModifyLiquidityParams memory _params,) = |
||
| 263 |
Fuzzers.createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 264 | |||
| 265 |
(int16 wordPos, uint8 bitPos) = TickBitmap.position(_params.tickLower / key.tickSpacing); |
||
| 266 |
(int16 wordPosUpper, uint8 bitPosUpper) = TickBitmap.position(_params.tickUpper / key.tickSpacing); |
||
| 267 | |||
| 268 |
uint256 tickBitmap = StateLibrary.getTickBitmap(manager, poolId, wordPos); |
||
| 269 |
assertNotEq(tickBitmap, 0); |
||
| 270 | |||
| 271 |
// in fuzz tests, the tickLower and tickUpper might exist on the same word |
||
| 272 |
if (wordPos == wordPosUpper) {
|
||
| 273 |
assertEq(tickBitmap, (1 << bitPos) | (1 << bitPosUpper)); |
||
| 274 |
} else {
|
||
| 275 |
assertEq(tickBitmap, 1 << bitPos); |
||
| 276 |
} |
||
| 277 |
} |
||
| 278 | |||
| 279 |
function test_getPositionInfo() public {
|
||
| 280 |
// create liquidity |
||
| 281 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 282 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES |
||
| 283 |
); |
||
| 284 | |||
| 285 |
// swap to create fees, crossing a tick |
||
| 286 |
uint256 swapAmount = 10 ether; |
||
| 287 |
swap(key, true, -int256(swapAmount), ZERO_BYTES); |
||
| 288 |
(, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId); |
||
| 289 |
assertNotEq(currentTick, -139); |
||
| 290 | |||
| 291 |
// poke the LP so that fees are updated |
||
| 292 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 0, 0), ZERO_BYTES); |
||
| 293 | |||
| 294 |
bytes32 positionId = |
||
| 295 |
keccak256(abi.encodePacked(address(modifyLiquidityRouter), int24(-60), int24(60), bytes32(0))); |
||
| 296 | |||
| 297 |
(uint128 liquidity, uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = |
||
| 298 |
StateLibrary.getPositionInfo(manager, poolId, positionId); |
||
| 299 |
snapLastCall("extsload getPositionInfo");
|
||
| 300 | |||
| 301 |
assertEq(liquidity, 10_000 ether); |
||
| 302 | |||
| 303 |
assertNotEq(feeGrowthInside0X128, 0); |
||
| 304 |
assertEq(feeGrowthInside1X128, 0); |
||
| 305 |
} |
||
| 306 | |||
| 307 |
function test_fuzz_getPositionInfo( |
||
| 308 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 309 |
uint256 swapAmount, |
||
| 310 |
bool zeroForOne |
||
| 311 |
) public {
|
||
| 312 |
(IPoolManager.ModifyLiquidityParams memory _params, BalanceDelta delta) = |
||
| 313 |
createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 314 | |||
| 315 |
uint256 delta0 = uint256(int256(-delta.amount0())); |
||
| 316 |
uint256 delta1 = uint256(int256(-delta.amount1())); |
||
| 317 |
// if one of the deltas is zero, ensure to swap in the right direction |
||
| 318 |
if (delta0 == 0) {
|
||
| 319 |
zeroForOne = true; |
||
| 320 |
} else if (delta1 == 0) {
|
||
| 321 |
zeroForOne = false; |
||
| 322 |
} |
||
| 323 |
swapAmount = bound(swapAmount, 1, uint256(int256(type(int128).max))); |
||
| 324 |
swap(key, zeroForOne, -int256(swapAmount), ZERO_BYTES); |
||
| 325 | |||
| 326 |
// poke the LP so that fees are updated |
||
| 327 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 328 |
key, IPoolManager.ModifyLiquidityParams(_params.tickLower, _params.tickUpper, 0, 0), ZERO_BYTES |
||
| 329 |
); |
||
| 330 | |||
| 331 |
bytes32 positionId = keccak256( |
||
| 332 |
abi.encodePacked(address(modifyLiquidityRouter), _params.tickLower, _params.tickUpper, bytes32(0)) |
||
| 333 |
); |
||
| 334 | |||
| 335 |
(uint128 liquidity, uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = |
||
| 336 |
StateLibrary.getPositionInfo(manager, poolId, positionId); |
||
| 337 | |||
| 338 |
assertEq(liquidity, uint128(uint256(_params.liquidityDelta))); |
||
| 339 |
if (zeroForOne) {
|
||
| 340 |
assertNotEq(feeGrowthInside0X128, 0); |
||
| 341 |
assertEq(feeGrowthInside1X128, 0); |
||
| 342 |
} else {
|
||
| 343 |
assertEq(feeGrowthInside0X128, 0); |
||
| 344 |
assertNotEq(feeGrowthInside1X128, 0); |
||
| 345 |
} |
||
| 346 |
} |
||
| 347 | |||
| 348 |
function test_getTickFeeGrowthOutside() public {
|
||
| 349 |
// create liquidity |
||
| 350 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 351 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES |
||
| 352 |
); |
||
| 353 | |||
| 354 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 355 |
key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES |
||
| 356 |
); |
||
| 357 | |||
| 358 |
// swap to create fees, crossing a tick |
||
| 359 |
uint256 swapAmount = 100 ether; |
||
| 360 |
swap(key, true, -int256(swapAmount), ZERO_BYTES); |
||
| 361 |
(, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId); |
||
| 362 |
assertEq(currentTick, -139); |
||
| 363 | |||
| 364 |
int24 tick = -60; |
||
| 365 |
(uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) = |
||
| 366 |
StateLibrary.getTickFeeGrowthOutside(manager, poolId, tick); |
||
| 367 |
snapLastCall("extsload getTickFeeGrowthOutside");
|
||
| 368 | |||
| 369 |
// magic number verified against a native getter on PoolManager |
||
| 370 |
assertEq(feeGrowthOutside0X128, 3076214778951936192155253373200636); |
||
| 371 |
assertEq(feeGrowthOutside1X128, 0); |
||
| 372 | |||
| 373 |
tick = 60; |
||
| 374 |
(feeGrowthOutside0X128, feeGrowthOutside1X128) = StateLibrary.getTickFeeGrowthOutside(manager, poolId, tick); |
||
| 375 |
assertEq(feeGrowthOutside0X128, 0); |
||
| 376 |
assertEq(feeGrowthOutside1X128, 0); |
||
| 377 |
} |
||
| 378 | |||
| 379 |
// also hard to fuzz because of feeGrowthOutside |
||
| 380 |
function test_getTickInfo() public {
|
||
| 381 |
// create liquidity |
||
| 382 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 383 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES |
||
| 384 |
); |
||
| 385 | |||
| 386 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 387 |
key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES |
||
| 388 |
); |
||
| 389 | |||
| 390 |
// swap to create fees, crossing a tick |
||
| 391 |
uint256 swapAmount = 100 ether; |
||
| 392 |
swap(key, true, -int256(swapAmount), ZERO_BYTES); |
||
| 393 |
(, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId); |
||
| 394 |
assertEq(currentTick, -139); |
||
| 395 | |||
| 396 |
int24 tick = -60; |
||
| 397 |
(uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) = |
||
| 398 |
StateLibrary.getTickInfo(manager, poolId, tick); |
||
| 399 |
snapLastCall("extsload getTickInfo");
|
||
| 400 | |||
| 401 |
(uint128 liquidityGross_, int128 liquidityNet_) = StateLibrary.getTickLiquidity(manager, poolId, tick); |
||
| 402 |
(uint256 feeGrowthOutside0X128_, uint256 feeGrowthOutside1X128_) = |
||
| 403 |
StateLibrary.getTickFeeGrowthOutside(manager, poolId, tick); |
||
| 404 | |||
| 405 |
assertEq(liquidityGross, 10_000 ether); |
||
| 406 |
assertEq(liquidityGross, liquidityGross_); |
||
| 407 |
assertEq(liquidityNet, liquidityNet_); |
||
| 408 | |||
| 409 |
assertNotEq(feeGrowthOutside0X128, 0); |
||
| 410 |
assertEq(feeGrowthOutside1X128, 0); |
||
| 411 |
assertEq(feeGrowthOutside0X128, feeGrowthOutside0X128_); |
||
| 412 |
assertEq(feeGrowthOutside1X128, feeGrowthOutside1X128_); |
||
| 413 |
} |
||
| 414 | |||
| 415 |
function test_getFeeGrowthInside() public {
|
||
| 416 |
// create liquidity |
||
| 417 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 418 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES |
||
| 419 |
); |
||
| 420 | |||
| 421 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 422 |
key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES |
||
| 423 |
); |
||
| 424 | |||
| 425 |
// swap to create fees, crossing a tick |
||
| 426 |
uint256 swapAmount = 100 ether; |
||
| 427 |
swap(key, true, -int256(swapAmount), ZERO_BYTES); |
||
| 428 |
(, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId); |
||
| 429 |
assertEq(currentTick, -139); |
||
| 430 | |||
| 431 |
// calculated live |
||
| 432 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = |
||
| 433 |
StateLibrary.getFeeGrowthInside(manager, poolId, -60, 60); |
||
| 434 |
snapLastCall("extsload getFeeGrowthInside");
|
||
| 435 | |||
| 436 |
// poke the LP so that fees are updated |
||
| 437 |
modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 0, 0), ZERO_BYTES); |
||
| 438 | |||
| 439 |
bytes32 positionId = |
||
| 440 |
keccak256(abi.encodePacked(address(modifyLiquidityRouter), int24(-60), int24(60), bytes32(0))); |
||
| 441 | |||
| 442 |
(, uint256 feeGrowthInside0X128_, uint256 feeGrowthInside1X128_) = |
||
| 443 |
StateLibrary.getPositionInfo(manager, poolId, positionId); |
||
| 444 | |||
| 445 |
assertNotEq(feeGrowthInside0X128, 0); |
||
| 446 |
assertEq(feeGrowthInside0X128, feeGrowthInside0X128_); |
||
| 447 |
assertEq(feeGrowthInside1X128, feeGrowthInside1X128_); |
||
| 448 |
} |
||
| 449 | |||
| 450 |
function test_fuzz_getFeeGrowthInside(IPoolManager.ModifyLiquidityParams memory params, bool zeroForOne) public {
|
||
| 451 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 452 |
key, |
||
| 453 |
IPoolManager.ModifyLiquidityParams( |
||
| 454 |
TickMath.minUsableTick(key.tickSpacing), TickMath.maxUsableTick(key.tickSpacing), 10_000 ether, 0 |
||
| 455 |
), |
||
| 456 |
ZERO_BYTES |
||
| 457 |
); |
||
| 458 | |||
| 459 |
(IPoolManager.ModifyLiquidityParams memory _params,) = |
||
| 460 |
createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 461 | |||
| 462 |
swap(key, zeroForOne, -int256(100e18), ZERO_BYTES); |
||
| 463 | |||
| 464 |
// calculated live |
||
| 465 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = |
||
| 466 |
StateLibrary.getFeeGrowthInside(manager, poolId, _params.tickLower, _params.tickUpper); |
||
| 467 | |||
| 468 |
// poke the LP so that fees are updated |
||
| 469 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 470 |
key, IPoolManager.ModifyLiquidityParams(_params.tickLower, _params.tickUpper, 0, 0), ZERO_BYTES |
||
| 471 |
); |
||
| 472 |
bytes32 positionId = keccak256( |
||
| 473 |
abi.encodePacked(address(modifyLiquidityRouter), _params.tickLower, _params.tickUpper, bytes32(0)) |
||
| 474 |
); |
||
| 475 | |||
| 476 |
(, uint256 feeGrowthInside0X128_, uint256 feeGrowthInside1X128_) = |
||
| 477 |
StateLibrary.getPositionInfo(manager, poolId, positionId); |
||
| 478 | |||
| 479 |
assertEq(feeGrowthInside0X128, feeGrowthInside0X128_); |
||
| 480 |
assertEq(feeGrowthInside1X128, feeGrowthInside1X128_); |
||
| 481 |
} |
||
| 482 | |||
| 483 |
function test_getPositionLiquidity() public {
|
||
| 484 |
// create liquidity |
||
| 485 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 486 |
key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES |
||
| 487 |
); |
||
| 488 | |||
| 489 |
bytes32 positionId = |
||
| 490 |
keccak256(abi.encodePacked(address(modifyLiquidityRouter), int24(-60), int24(60), bytes32(0))); |
||
| 491 | |||
| 492 |
uint128 liquidity = StateLibrary.getPositionLiquidity(manager, poolId, positionId); |
||
| 493 |
snapLastCall("extsload getPositionLiquidity");
|
||
| 494 | |||
| 495 |
assertEq(liquidity, 10_000 ether); |
||
| 496 |
} |
||
| 497 | |||
| 498 |
function test_fuzz_getPositionLiquidity( |
||
| 499 |
IPoolManager.ModifyLiquidityParams memory paramsA, |
||
| 500 |
IPoolManager.ModifyLiquidityParams memory paramsB |
||
| 501 |
) public {
|
||
| 502 |
(IPoolManager.ModifyLiquidityParams memory _paramsA) = |
||
| 503 |
Fuzzers.createFuzzyLiquidityParams(key, paramsA, SQRT_PRICE_1_1); |
||
| 504 | |||
| 505 |
(IPoolManager.ModifyLiquidityParams memory _paramsB) = |
||
| 506 |
Fuzzers.createFuzzyLiquidityParams(key, paramsB, SQRT_PRICE_1_1); |
||
| 507 | |||
| 508 |
// Assume there are no overlapping positions |
||
| 509 |
vm.assume( |
||
| 510 |
_paramsA.tickLower != _paramsB.tickLower && _paramsA.tickLower != _paramsB.tickUpper |
||
| 511 |
&& _paramsB.tickLower != _paramsA.tickUpper && _paramsA.tickUpper != _paramsB.tickUpper |
||
| 512 |
); |
||
| 513 | |||
| 514 |
modifyLiquidityRouter.modifyLiquidity(key, _paramsA, ZERO_BYTES); |
||
| 515 |
modifyLiquidityRouter.modifyLiquidity(key, _paramsB, ZERO_BYTES); |
||
| 516 | |||
| 517 |
bytes32 positionIdA = keccak256( |
||
| 518 |
abi.encodePacked(address(modifyLiquidityRouter), _paramsA.tickLower, _paramsA.tickUpper, bytes32(0)) |
||
| 519 |
); |
||
| 520 |
uint128 liquidityA = StateLibrary.getPositionLiquidity(manager, poolId, positionIdA); |
||
| 521 |
assertEq(liquidityA, uint128(uint256(_paramsA.liquidityDelta))); |
||
| 522 | |||
| 523 |
bytes32 positionIdB = keccak256( |
||
| 524 |
abi.encodePacked(address(modifyLiquidityRouter), _paramsB.tickLower, _paramsB.tickUpper, bytes32(0)) |
||
| 525 |
); |
||
| 526 |
uint128 liquidityB = StateLibrary.getPositionLiquidity(manager, poolId, positionIdB); |
||
| 527 |
assertEq(liquidityB, uint128(uint256(_paramsB.liquidityDelta))); |
||
| 528 |
} |
||
| 529 |
} |
||
| 530 |
| Lines covered: | 0 / 146 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {SqrtPriceMath} from "../../src/libraries/SqrtPriceMath.sol";
|
||
| 7 |
import {SwapMath} from "../../src/libraries/SwapMath.sol";
|
||
| 8 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 9 | |||
| 10 |
contract SwapMathTest is Test, GasSnapshot {
|
||
| 11 |
uint160 private constant SQRT_PRICE_1_1 = 79228162514264337593543950336; |
||
| 12 |
uint160 private constant SQRT_PRICE_99_100 = 78831026366734652303669917531; |
||
| 13 |
uint160 private constant SQRT_PRICE_99_1000 = 24928559360766947368818086097; |
||
| 14 |
uint160 private constant SQRT_PRICE_101_100 = 79623317895830914510639640423; |
||
| 15 |
uint160 private constant SQRT_PRICE_1000_100 = 250541448375047931186413801569; |
||
| 16 |
uint160 private constant SQRT_PRICE_1010_100 = 251791039410471229173201122529; |
||
| 17 |
uint160 private constant SQRT_PRICE_10000_100 = 792281625142643375935439503360; |
||
| 18 | |||
| 19 |
function test_fuzz_getSqrtPriceTarget(bool zeroForOne, uint160 sqrtPriceNextX96, uint160 sqrtPriceLimitX96) |
||
| 20 |
public |
||
| 21 |
pure |
||
| 22 |
{
|
||
| 23 |
assertEq( |
||
| 24 |
SwapMath.getSqrtPriceTarget(zeroForOne, sqrtPriceNextX96, sqrtPriceLimitX96), |
||
| 25 |
(zeroForOne ? sqrtPriceNextX96 < sqrtPriceLimitX96 : sqrtPriceNextX96 > sqrtPriceLimitX96) |
||
| 26 |
? sqrtPriceLimitX96 |
||
| 27 |
: sqrtPriceNextX96 |
||
| 28 |
); |
||
| 29 |
} |
||
| 30 | |||
| 31 |
function test_computeSwapStep_exactAmountIn_oneForZero_thatGetsCappedAtPriceTargetIn() public pure {
|
||
| 32 |
uint160 priceTarget = SQRT_PRICE_101_100; |
||
| 33 |
uint160 price = SQRT_PRICE_1_1; |
||
| 34 |
uint128 liquidity = 2 ether; |
||
| 35 |
int256 amount = (1 ether) * -1; |
||
| 36 |
uint24 lpFee = 600; |
||
| 37 |
bool zeroForOne = false; |
||
| 38 | |||
| 39 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 40 |
SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee); |
||
| 41 | |||
| 42 |
assertEq(amountIn, 9975124224178055); |
||
| 43 |
assertEq(amountOut, 9925619580021728); |
||
| 44 |
assertEq(feeAmount, 5988667735148); |
||
| 45 |
assert(amountIn + feeAmount < uint256(amount * -1)); |
||
| 46 | |||
| 47 |
uint256 priceAfterWholeInputAmount = |
||
| 48 |
SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, uint256(amount * -1), zeroForOne); |
||
| 49 | |||
| 50 |
assertEq(sqrtQ, priceTarget); |
||
| 51 |
assert(sqrtQ < priceAfterWholeInputAmount); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
function test_computeSwapStep_exactAmountOut_oneForZero_thatGetsCappedAtPriceTargetIn() public pure {
|
||
| 55 |
uint160 priceTarget = SQRT_PRICE_101_100; |
||
| 56 |
uint160 price = SQRT_PRICE_1_1; |
||
| 57 |
uint128 liquidity = 2 ether; |
||
| 58 |
int256 amount = 1 ether; |
||
| 59 |
uint24 lpFee = 600; |
||
| 60 |
bool zeroForOne = false; |
||
| 61 | |||
| 62 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 63 |
SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee); |
||
| 64 | |||
| 65 |
assertEq(amountIn, 9975124224178055); |
||
| 66 |
assertEq(amountOut, 9925619580021728); |
||
| 67 |
assertEq(feeAmount, 5988667735148); |
||
| 68 |
assert(amountOut < uint256(amount)); |
||
| 69 | |||
| 70 |
uint256 priceAfterWholeOutputAmount = |
||
| 71 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, uint256(amount), zeroForOne); |
||
| 72 | |||
| 73 |
assertEq(sqrtQ, priceTarget); |
||
| 74 |
assert(sqrtQ < priceAfterWholeOutputAmount); |
||
| 75 |
} |
||
| 76 | |||
| 77 |
function test_computeSwapStep_exactAmountIn_oneForZero_thatIsFullySpentIn() public pure {
|
||
| 78 |
uint160 priceTarget = SQRT_PRICE_1000_100; |
||
| 79 |
uint160 price = SQRT_PRICE_1_1; |
||
| 80 |
uint128 liquidity = 2 ether; |
||
| 81 |
int256 amount = 1 ether * -1; |
||
| 82 |
uint24 lpFee = 600; |
||
| 83 |
bool zeroForOne = false; |
||
| 84 | |||
| 85 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 86 |
SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee); |
||
| 87 | |||
| 88 |
assertEq(amountIn, 999400000000000000); |
||
| 89 |
assertEq(amountOut, 666399946655997866); |
||
| 90 |
assertEq(feeAmount, 600000000000000); |
||
| 91 |
assertEq(amountIn + feeAmount, uint256(-amount)); |
||
| 92 | |||
| 93 |
uint256 priceAfterWholeInputAmountLessFee = |
||
| 94 |
SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, uint256(uint256(-amount) - feeAmount), zeroForOne); |
||
| 95 | |||
| 96 |
assert(sqrtQ < priceTarget); |
||
| 97 |
assertEq(sqrtQ, priceAfterWholeInputAmountLessFee); |
||
| 98 |
} |
||
| 99 | |||
| 100 |
function test_computeSwapStep_exactAmountOut_oneForZero_thatIsFullyReceivedIn() public pure {
|
||
| 101 |
uint160 priceTarget = SQRT_PRICE_10000_100; |
||
| 102 |
uint160 price = SQRT_PRICE_1_1; |
||
| 103 |
uint128 liquidity = 2 ether; |
||
| 104 |
int256 amount = (1 ether); |
||
| 105 |
uint24 lpFee = 600; |
||
| 106 |
bool zeroForOne = false; |
||
| 107 | |||
| 108 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 109 |
SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee); |
||
| 110 | |||
| 111 |
assertEq(amountIn, 2000000000000000000); |
||
| 112 |
assertEq(feeAmount, 1200720432259356); |
||
| 113 |
assertEq(amountOut, uint256(amount)); |
||
| 114 | |||
| 115 |
uint256 priceAfterWholeOutputAmount = |
||
| 116 |
SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, uint256(amount), zeroForOne); |
||
| 117 | |||
| 118 |
assert(sqrtQ < priceTarget); |
||
| 119 |
assertEq(sqrtQ, priceAfterWholeOutputAmount); |
||
| 120 |
} |
||
| 121 | |||
| 122 |
function test_computeSwapStep_amountOut_isCappedAtTheDesiredAmountOut() public pure {
|
||
| 123 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = SwapMath.computeSwapStep( |
||
| 124 |
417332158212080721273783715441582, 1452870262520218020823638996, 159344665391607089467575320103, 1, 1 |
||
| 125 |
); |
||
| 126 | |||
| 127 |
assertEq(amountIn, 1); |
||
| 128 |
assertEq(feeAmount, 1); |
||
| 129 |
assertEq(amountOut, 1); // would be 2 if not capped |
||
| 130 |
assertEq(sqrtQ, 417332158212080721273783715441581); |
||
| 131 |
} |
||
| 132 | |||
| 133 |
function test_computeSwapStep_targetPriceOf1UsesPartialInputAmount() public pure {
|
||
| 134 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 135 |
SwapMath.computeSwapStep(2, 1, 1, -3915081100057732413702495386755767, 1); |
||
| 136 |
assertEq(amountIn, 39614081257132168796771975168); |
||
| 137 |
assertEq(feeAmount, 39614120871253040049813); |
||
| 138 |
assert(amountIn + feeAmount <= 3915081100057732413702495386755767); |
||
| 139 |
assertEq(amountOut, 0); |
||
| 140 |
assertEq(sqrtQ, 1); |
||
| 141 |
} |
||
| 142 | |||
| 143 |
function test_computeSwapStep_entireInputAmountTakenAsFee() public pure {
|
||
| 144 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 145 |
SwapMath.computeSwapStep(2413, 79887613182836312, 1985041575832132834610021537970, -10, 1872); |
||
| 146 | |||
| 147 |
assertEq(amountIn, 0); |
||
| 148 |
assertEq(feeAmount, 10); |
||
| 149 |
assertEq(amountOut, 0); |
||
| 150 |
assertEq(sqrtQ, 2413); |
||
| 151 |
} |
||
| 152 | |||
| 153 |
function test_computeSwapStep_zeroForOne_handlesIntermediateInsufficientLiquidityInExactOutputCase() public pure {
|
||
| 154 |
uint160 sqrtP = 20282409603651670423947251286016; |
||
| 155 |
uint160 sqrtPTarget = (sqrtP * 11) / 10; |
||
| 156 |
uint128 liquidity = 1024; |
||
| 157 |
// virtual reserves of one are only 4 |
||
| 158 |
// https://www.wolframalpha.com/input/?i=1024+%2F+%2820282409603651670423947251286016+%2F+2**96%29 |
||
| 159 |
int256 amountRemaining = 4; |
||
| 160 |
uint24 feePips = 3000; |
||
| 161 | |||
| 162 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 163 |
SwapMath.computeSwapStep(sqrtP, sqrtPTarget, liquidity, amountRemaining, feePips); |
||
| 164 | |||
| 165 |
assertEq(amountOut, 0); |
||
| 166 |
assertEq(sqrtQ, sqrtPTarget); |
||
| 167 |
assertEq(amountIn, 26215); |
||
| 168 |
assertEq(feeAmount, 79); |
||
| 169 |
} |
||
| 170 | |||
| 171 |
function test_computeSwapStep_oneForZero_handlesIntermediateInsufficientLiquidityInExactOutputCase() public pure {
|
||
| 172 |
uint160 sqrtP = 20282409603651670423947251286016; |
||
| 173 |
uint160 sqrtPTarget = (sqrtP * 9) / 10; |
||
| 174 |
uint128 liquidity = 1024; |
||
| 175 |
// virtual reserves of zero are only 262144 |
||
| 176 |
// https://www.wolframalpha.com/input/?i=1024+*+%2820282409603651670423947251286016+%2F+2**96%29 |
||
| 177 |
int256 amountRemaining = 263000; |
||
| 178 |
uint24 feePips = 3000; |
||
| 179 | |||
| 180 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 181 |
SwapMath.computeSwapStep(sqrtP, sqrtPTarget, liquidity, amountRemaining, feePips); |
||
| 182 | |||
| 183 |
assertEq(amountOut, 26214); |
||
| 184 |
assertEq(sqrtQ, sqrtPTarget); |
||
| 185 |
assertEq(amountIn, 1); |
||
| 186 |
assertEq(feeAmount, 1); |
||
| 187 |
} |
||
| 188 | |||
| 189 |
function test_fuzz_computeSwapStep( |
||
| 190 |
uint160 sqrtPriceRaw, |
||
| 191 |
uint160 sqrtPriceTargetRaw, |
||
| 192 |
uint128 liquidity, |
||
| 193 |
int256 amountRemaining, |
||
| 194 |
uint24 feePips |
||
| 195 |
) public pure {
|
||
| 196 |
vm.assume(sqrtPriceRaw > 0); |
||
| 197 |
vm.assume(sqrtPriceTargetRaw > 0); |
||
| 198 |
vm.assume(feePips >= 0); |
||
| 199 | |||
| 200 |
if (amountRemaining >= 0) {
|
||
| 201 |
vm.assume(feePips < 1e6); |
||
| 202 |
} else {
|
||
| 203 |
vm.assume(feePips <= 1e6); |
||
| 204 |
} |
||
| 205 | |||
| 206 |
(uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = |
||
| 207 |
SwapMath.computeSwapStep(sqrtPriceRaw, sqrtPriceTargetRaw, liquidity, amountRemaining, feePips); |
||
| 208 | |||
| 209 |
assertLe(amountIn, type(uint256).max - feeAmount); |
||
| 210 | |||
| 211 |
unchecked {
|
||
| 212 |
if (amountRemaining >= 0) {
|
||
| 213 |
assertLe(amountOut, uint256(amountRemaining)); |
||
| 214 |
} else {
|
||
| 215 |
assertLe(amountIn + feeAmount, uint256(-amountRemaining)); |
||
| 216 |
} |
||
| 217 |
} |
||
| 218 | |||
| 219 |
if (sqrtPriceRaw == sqrtPriceTargetRaw) {
|
||
| 220 |
assertEq(amountIn, 0); |
||
| 221 |
assertEq(amountOut, 0); |
||
| 222 |
assertEq(feeAmount, 0); |
||
| 223 |
assertEq(sqrtQ, sqrtPriceTargetRaw); |
||
| 224 |
} |
||
| 225 | |||
| 226 |
// didn't reach price target, entire amount must be consumed |
||
| 227 |
if (sqrtQ != sqrtPriceTargetRaw) {
|
||
| 228 |
uint256 absAmtRemaining; |
||
| 229 |
if (amountRemaining == type(int256).min) {
|
||
| 230 |
absAmtRemaining = uint256(type(int256).max) + 1; |
||
| 231 |
} else if (amountRemaining < 0) {
|
||
| 232 |
absAmtRemaining = uint256(-amountRemaining); |
||
| 233 |
} else {
|
||
| 234 |
absAmtRemaining = uint256(amountRemaining); |
||
| 235 |
} |
||
| 236 |
if (amountRemaining > 0) assertEq(amountOut, absAmtRemaining); |
||
| 237 |
else assertEq(amountIn + feeAmount, absAmtRemaining); |
||
| 238 |
} |
||
| 239 | |||
| 240 |
// next price is between price and price target |
||
| 241 |
if (sqrtPriceTargetRaw <= sqrtPriceRaw) {
|
||
| 242 |
assertLe(sqrtQ, sqrtPriceRaw); |
||
| 243 |
assertGe(sqrtQ, sqrtPriceTargetRaw); |
||
| 244 |
} else {
|
||
| 245 |
assertGe(sqrtQ, sqrtPriceRaw); |
||
| 246 |
assertLe(sqrtQ, sqrtPriceTargetRaw); |
||
| 247 |
} |
||
| 248 |
} |
||
| 249 | |||
| 250 |
function test_computeSwapStep_swapOneForZero_exactInCapped() public {
|
||
| 251 |
snapStart("SwapMath_oneForZero_exactInCapped");
|
||
| 252 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_101_100, 2 ether, (1 ether) * -1, 600); |
||
| 253 |
snapEnd(); |
||
| 254 |
} |
||
| 255 | |||
| 256 |
function test_computeSwapStep_swapZeroForOne_exactInCapped() public {
|
||
| 257 |
snapStart("SwapMath_zeroForOne_exactInCapped");
|
||
| 258 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_100, 2 ether, (1 ether) * -1, 600); |
||
| 259 |
snapEnd(); |
||
| 260 |
} |
||
| 261 | |||
| 262 |
function test_computeSwapStep_swapOneForZero_exactOutCapped() public {
|
||
| 263 |
snapStart("SwapMath_oneForZero_exactOutCapped");
|
||
| 264 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_101_100, 2 ether, 1 ether, 600); |
||
| 265 |
snapEnd(); |
||
| 266 |
} |
||
| 267 | |||
| 268 |
function test_computeSwapStep_swapZeroForOne_exactOutCapped() public {
|
||
| 269 |
snapStart("SwapMath_zeroForOne_exactOutCapped");
|
||
| 270 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_100, 2 ether, 1 ether, 600); |
||
| 271 |
snapEnd(); |
||
| 272 |
} |
||
| 273 | |||
| 274 |
function test_computeSwapStep_swapOneForZero_exactInPartial() public {
|
||
| 275 |
snapStart("SwapMath_oneForZero_exactInPartial");
|
||
| 276 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_1010_100, 2 ether, 1_000 * -1, 600); |
||
| 277 |
snapEnd(); |
||
| 278 |
} |
||
| 279 | |||
| 280 |
function test_computeSwapStep_swapZeroForOne_exactInPartial() public {
|
||
| 281 |
snapStart("SwapMath_zeroForOne_exactInPartial");
|
||
| 282 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_1000, 2 ether, 1_000 * -1, 600); |
||
| 283 |
snapEnd(); |
||
| 284 |
} |
||
| 285 | |||
| 286 |
function test_computeSwapStep_swapOneForZero_exactOutPartial() public {
|
||
| 287 |
snapStart("SwapMath_oneForZero_exactOutPartial");
|
||
| 288 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_1010_100, 2 ether, 1_000, 600); |
||
| 289 |
snapEnd(); |
||
| 290 |
} |
||
| 291 | |||
| 292 |
function test_computeSwapStep_swapZeroForOne_exactOutPartial() public {
|
||
| 293 |
snapStart("SwapMath_zeroForOne_exactOutPartial");
|
||
| 294 |
SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_1000, 2 ether, 1_000, 600); |
||
| 295 |
snapEnd(); |
||
| 296 |
} |
||
| 297 |
} |
||
| 298 |
| Lines covered: | 0 / 138 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 6 |
import {GasSnapshot} from "lib/forge-gas-snapshot/src/GasSnapshot.sol";
|
||
| 7 |
import {TickBitmap} from "../../src/libraries/TickBitmap.sol";
|
||
| 8 |
import {TickMath} from "../../src/libraries/TickMath.sol";
|
||
| 9 | |||
| 10 |
contract TickBitmapTest is Test, GasSnapshot {
|
||
| 11 |
using TickBitmap for mapping(int16 => uint256); |
||
| 12 | |||
| 13 |
int24 constant INITIALIZED_TICK = 70; |
||
| 14 |
int24 constant TICK_IN_UNINITIALZIED_WORD = 10000; |
||
| 15 |
int24 constant SOLO_INITIALIZED_TICK_IN_WORD = -10000; |
||
| 16 | |||
| 17 |
mapping(int16 => uint256) public bitmap; |
||
| 18 |
mapping(int16 => uint256) internal emptyBitmap; |
||
| 19 | |||
| 20 |
function setUp() public {
|
||
| 21 |
// set dirty slots beforehand for certain gas tests |
||
| 22 |
int24[10] memory ticks = [SOLO_INITIALIZED_TICK_IN_WORD, -200, -55, -4, INITIALIZED_TICK, 78, 84, 139, 240, 535]; |
||
| 23 |
for (uint256 i; i < ticks.length - 1; i++) {
|
||
| 24 |
flipTick(ticks[i]); |
||
| 25 |
} |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function test_fuzz_compress(int24 tick, int24 tickSpacing) public pure {
|
||
| 29 |
tickSpacing = int24(bound(tickSpacing, 1, type(int24).max)); |
||
| 30 |
int24 compressed = tick / tickSpacing; |
||
| 31 |
if (tick < 0 && tick % tickSpacing != 0) compressed--; |
||
| 32 |
assertEq(TickBitmap.compress(tick, tickSpacing), compressed); |
||
| 33 |
} |
||
| 34 | |||
| 35 |
function test_fuzz_position(int24 tick) public pure {
|
||
| 36 |
(int16 wordPos, uint8 bitPos) = TickBitmap.position(tick); |
||
| 37 |
assertEq(wordPos, tick >> 8); |
||
| 38 |
assertEq(bitPos, uint8(int8(tick % 256))); |
||
| 39 |
} |
||
| 40 | |||
| 41 |
function test_isInitialized_isFalseAtFirst() public view {
|
||
| 42 |
assertEq(isInitialized(1), false); |
||
| 43 |
} |
||
| 44 | |||
| 45 |
function test_isInitialized_isFlippedByFlipTick() public {
|
||
| 46 |
flipTick(1); |
||
| 47 |
assertEq(isInitialized(1), true); |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function test_isInitialized_isFlippedBackByFlipTick() public {
|
||
| 51 |
flipTick(1); |
||
| 52 |
flipTick(1); |
||
| 53 |
assertEq(isInitialized(1), false); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function test_isInitialized_isNotChangedByAnotherFlipToADifferentTick() public {
|
||
| 57 |
flipTick(2); |
||
| 58 |
assertEq(isInitialized(1), false); |
||
| 59 |
} |
||
| 60 | |||
| 61 |
function test_isInitialized_isNotChangedByAnotherFlipToADifferentTickOnAnotherWord() public {
|
||
| 62 |
flipTick(1 + 256); |
||
| 63 |
assertEq(isInitialized(257), true); |
||
| 64 |
assertEq(isInitialized(1), false); |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function test_flipTick_flipsOnlyTheSpecifiedTick() public {
|
||
| 68 |
flipTick(-230); |
||
| 69 |
assertEq(isInitialized(-230), true); |
||
| 70 |
assertEq(isInitialized(-231), false); |
||
| 71 |
assertEq(isInitialized(-229), false); |
||
| 72 |
assertEq(isInitialized(-230 + 256), false); |
||
| 73 |
assertEq(isInitialized(-230 - 256), false); |
||
| 74 | |||
| 75 |
flipTick(-230); |
||
| 76 |
assertEq(isInitialized(-230), false); |
||
| 77 |
assertEq(isInitialized(-231), false); |
||
| 78 |
assertEq(isInitialized(-229), false); |
||
| 79 |
assertEq(isInitialized(-230 + 256), false); |
||
| 80 |
assertEq(isInitialized(-230 - 256), false); |
||
| 81 | |||
| 82 |
assertEq(isInitialized(1), false); |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function test_flipTick_revertsOnlyItself() public {
|
||
| 86 |
flipTick(-230); |
||
| 87 |
flipTick(-259); |
||
| 88 |
flipTick(-229); |
||
| 89 |
flipTick(500); |
||
| 90 |
flipTick(-259); |
||
| 91 |
flipTick(-229); |
||
| 92 |
flipTick(-259); |
||
| 93 |
assertEq(isInitialized(-259), true); |
||
| 94 |
assertEq(isInitialized(-229), false); |
||
| 95 |
} |
||
| 96 | |||
| 97 |
function test_flipTick_flippingFirstTickInWordToInitialized_gas() public {
|
||
| 98 |
snapStart("flipTick_flippingFirstTickInWordToInitialized");
|
||
| 99 |
flipTick(TICK_IN_UNINITIALZIED_WORD); |
||
| 100 |
snapEnd(); |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function test_flipTick_flippingSecondTickInWordToInitialized_gas() public {
|
||
| 104 |
snapStart("flipTick_flippingSecondTickInWordToInitialized");
|
||
| 105 |
flipTick(INITIALIZED_TICK + 1); |
||
| 106 |
snapEnd(); |
||
| 107 |
} |
||
| 108 | |||
| 109 |
function test_flipTick_flippingATickThatResultsInDeletingAWord_gas() public {
|
||
| 110 |
snapStart("flipTick_flippingATickThatResultsInDeletingAWord");
|
||
| 111 |
flipTick(SOLO_INITIALIZED_TICK_IN_WORD); |
||
| 112 |
snapEnd(); |
||
| 113 |
} |
||
| 114 | |||
| 115 |
function test_fuzz_flipTick(int24 tick, int24 tickSpacing) public {
|
||
| 116 |
tickSpacing = int24(bound(tickSpacing, 1, type(int24).max)); |
||
| 117 | |||
| 118 |
if (tick % tickSpacing != 0) {
|
||
| 119 |
vm.expectRevert(abi.encodeWithSelector(TickBitmap.TickMisaligned.selector, tick, tickSpacing)); |
||
| 120 |
bitmap.flipTick(tick, tickSpacing); |
||
| 121 |
} else {
|
||
| 122 |
bool initialized = isInitialized(tick, tickSpacing); |
||
| 123 |
bitmap.flipTick(tick, tickSpacing); |
||
| 124 |
assertEq(isInitialized(tick, tickSpacing), !initialized); |
||
| 125 |
// flip again |
||
| 126 |
bitmap.flipTick(tick, tickSpacing); |
||
| 127 |
assertEq(isInitialized(tick, tickSpacing), initialized); |
||
| 128 |
} |
||
| 129 |
} |
||
| 130 | |||
| 131 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTickToRightIfAtInitializedTick() public view {
|
||
| 132 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(78, 1, false); |
||
| 133 |
assertEq(next, 84); |
||
| 134 |
assertEq(initialized, true); |
||
| 135 |
} |
||
| 136 | |||
| 137 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTickToRightIfAtInitializedTick2() public view {
|
||
| 138 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-55, 1, false); |
||
| 139 | |||
| 140 |
assertEq(next, -4); |
||
| 141 |
assertEq(initialized, true); |
||
| 142 |
} |
||
| 143 | |||
| 144 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheTickDirectlyToTheRight() public view {
|
||
| 145 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(77, 1, false); |
||
| 146 |
assertEq(next, 78); |
||
| 147 |
assertEq(initialized, true); |
||
| 148 |
} |
||
| 149 | |||
| 150 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheTickDirectlyToTheRight2() public view {
|
||
| 151 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-56, 1, false); |
||
| 152 |
assertEq(next, -55); |
||
| 153 |
assertEq(initialized, true); |
||
| 154 |
} |
||
| 155 | |||
| 156 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheNextWordsInitializedTickIfOnTheRightBoundary() |
||
| 157 |
public |
||
| 158 |
view |
||
| 159 |
{
|
||
| 160 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(255, 1, false); |
||
| 161 |
assertEq(next, 511); |
||
| 162 |
assertEq(initialized, false); |
||
| 163 |
} |
||
| 164 | |||
| 165 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheNextWordsInitializedTickIfOnTheRightBoundary2() |
||
| 166 |
public |
||
| 167 |
view |
||
| 168 |
{
|
||
| 169 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-257, 1, false); |
||
| 170 |
assertEq(next, -200); |
||
| 171 |
assertEq(initialized, true); |
||
| 172 |
} |
||
| 173 | |||
| 174 |
function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheNextInitializedTickFromTheNextWord() public {
|
||
| 175 |
flipTick(340); |
||
| 176 | |||
| 177 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(328, 1, false); |
||
| 178 |
assertEq(next, 340); |
||
| 179 |
assertEq(initialized, true); |
||
| 180 |
} |
||
| 181 | |||
| 182 |
function test_nextInitializedTickWithinOneWord_lteFalse_doesNotExceedBoundary() public view {
|
||
| 183 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(508, 1, false); |
||
| 184 |
assertEq(next, 511); |
||
| 185 |
assertEq(initialized, false); |
||
| 186 |
} |
||
| 187 | |||
| 188 |
function test_nextInitializedTickWithinOneWord_lteFalse_skipsEntireWord() public view {
|
||
| 189 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(255, 1, false); |
||
| 190 |
assertEq(next, 511); |
||
| 191 |
assertEq(initialized, false); |
||
| 192 |
} |
||
| 193 | |||
| 194 |
function test_nextInitializedTickWithinOneWord_lteFalse_skipsHalfWord() public view {
|
||
| 195 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(383, 1, false); |
||
| 196 |
assertEq(next, 511); |
||
| 197 |
assertEq(initialized, false); |
||
| 198 |
} |
||
| 199 | |||
| 200 |
function test_nextInitializedTickWithinOneWord_lteFalse_onBoundary_gas() public {
|
||
| 201 |
snapStart("nextInitializedTickWithinOneWord_lteFalse_onBoundary");
|
||
| 202 |
bitmap.nextInitializedTickWithinOneWord(255, 1, false); |
||
| 203 |
snapEnd(); |
||
| 204 |
} |
||
| 205 | |||
| 206 |
function test_nextInitializedTickWithinOneWord_lteFalse_justBelowBoundary_gas() public {
|
||
| 207 |
snapStart("nextInitializedTickWithinOneWord_lteFalse_justBelowBoundary");
|
||
| 208 |
bitmap.nextInitializedTickWithinOneWord(254, 1, false); |
||
| 209 |
snapEnd(); |
||
| 210 |
} |
||
| 211 | |||
| 212 |
function test_nextInitializedTickWithinOneWord_lteFalse_forEntireWord_gas() public {
|
||
| 213 |
snapStart("nextInitializedTickWithinOneWord_lteFalse_forEntireWord");
|
||
| 214 |
bitmap.nextInitializedTickWithinOneWord(768, 1, false); |
||
| 215 |
snapEnd(); |
||
| 216 |
} |
||
| 217 | |||
| 218 |
function test_nextInitializedTickWithinOneWord_lteTrue_returnsSameTickIfInitialized() public view {
|
||
| 219 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(78, 1, true); |
||
| 220 |
assertEq(next, 78); |
||
| 221 |
assertEq(initialized, true); |
||
| 222 |
} |
||
| 223 | |||
| 224 |
function test_nextInitializedTickWithinOneWord_lteTrue_returnsTickDirectlyToTheLeftOfInputTickIfNotInitialized() |
||
| 225 |
public |
||
| 226 |
view |
||
| 227 |
{
|
||
| 228 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(79, 1, true); |
||
| 229 |
assertEq(next, 78); |
||
| 230 |
assertEq(initialized, true); |
||
| 231 |
} |
||
| 232 | |||
| 233 |
function test_nextInitializedTickWithinOneWord_lteTrue_willNotExceedTheWordBoundary() public view {
|
||
| 234 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(258, 1, true); |
||
| 235 |
assertEq(next, 256); |
||
| 236 |
assertEq(initialized, false); |
||
| 237 |
} |
||
| 238 | |||
| 239 |
function test_nextInitializedTickWithinOneWord_lteTrue_atTheWordBoundary() public view {
|
||
| 240 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(256, 1, true); |
||
| 241 |
assertEq(next, 256); |
||
| 242 |
assertEq(initialized, false); |
||
| 243 |
} |
||
| 244 | |||
| 245 |
function test_nextInitializedTickWithinOneWord_lteTrue_wordBoundaryLess1nextInitializedTickInNextWord() |
||
| 246 |
public |
||
| 247 |
view |
||
| 248 |
{
|
||
| 249 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(72, 1, true); |
||
| 250 |
assertEq(next, 70); |
||
| 251 |
assertEq(initialized, true); |
||
| 252 |
} |
||
| 253 | |||
| 254 |
function test_nextInitializedTickWithinOneWord_lteTrue_wordBoundary() public view {
|
||
| 255 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-257, 1, true); |
||
| 256 |
assertEq(next, -512); |
||
| 257 |
assertEq(initialized, false); |
||
| 258 |
} |
||
| 259 | |||
| 260 |
function test_nextInitializedTickWithinOneWord_lteTrue_entireEmptyWord() public view {
|
||
| 261 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(1023, 1, true); |
||
| 262 |
assertEq(next, 768); |
||
| 263 |
assertEq(initialized, false); |
||
| 264 |
} |
||
| 265 | |||
| 266 |
function test_nextInitializedTickWithinOneWord_lteTrue_halfwayThroughEmptyWord() public view {
|
||
| 267 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(900, 1, true); |
||
| 268 |
assertEq(next, 768); |
||
| 269 |
assertEq(initialized, false); |
||
| 270 |
} |
||
| 271 | |||
| 272 |
function test_nextInitializedTickWithinOneWord_lteTrue_boundaryIsInitialized() public {
|
||
| 273 |
flipTick(329); |
||
| 274 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(456, 1, true); |
||
| 275 |
assertEq(next, 329); |
||
| 276 |
assertEq(initialized, true); |
||
| 277 |
} |
||
| 278 | |||
| 279 |
function test_nextInitializedTickWithinOneWord_lteTrue_onBoundary_gas() public {
|
||
| 280 |
snapStart("nextInitializedTickWithinOneWord_lteTrue_onBoundary_gas");
|
||
| 281 |
bitmap.nextInitializedTickWithinOneWord(256, 1, true); |
||
| 282 |
snapEnd(); |
||
| 283 |
} |
||
| 284 | |||
| 285 |
function test_nextInitializedTickWithinOneWord_lteTrue_justBelowBoundary_gas() public {
|
||
| 286 |
snapStart("nextInitializedTickWithinOneWord_lteTrue_justBelowBoundary");
|
||
| 287 |
bitmap.nextInitializedTickWithinOneWord(255, 1, true); |
||
| 288 |
snapEnd(); |
||
| 289 |
} |
||
| 290 | |||
| 291 |
function test_nextInitializedTickWithinOneWord_lteTrue_forEntireWord_gas() public {
|
||
| 292 |
snapStart("nextInitializedTickWithinOneWord_lteTrue_forEntireWord");
|
||
| 293 |
bitmap.nextInitializedTickWithinOneWord(1024, 1, true); |
||
| 294 |
snapEnd(); |
||
| 295 |
} |
||
| 296 | |||
| 297 |
function test_fuzz_nextInitializedTickWithinOneWord(int24 tick, bool lte) public view {
|
||
| 298 |
// assume tick is at least one word inside type(int24).(max | min) |
||
| 299 |
vm.assume(lte ? tick >= -8388352 : tick < 8388351); |
||
| 300 | |||
| 301 |
(int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(tick, 1, lte); |
||
| 302 | |||
| 303 |
if (lte) {
|
||
| 304 |
assertLe(next, tick); |
||
| 305 |
assertLe(tick - next, 256); |
||
| 306 |
// all the ticks between the input tick and the next tick should be uninitialized |
||
| 307 |
for (int24 i = tick; i > next; i--) {
|
||
| 308 |
assertTrue(!isInitialized(i)); |
||
| 309 |
} |
||
| 310 |
assertEq(isInitialized(next), initialized); |
||
| 311 |
} else {
|
||
| 312 |
assertGt(next, tick); |
||
| 313 |
assertLe(next - tick, 256); |
||
| 314 |
// all the ticks between the input tick and the next tick should be uninitialized |
||
| 315 |
for (int24 i = tick + 1; i < next; i++) {
|
||
| 316 |
assertTrue(!isInitialized(i)); |
||
| 317 |
} |
||
| 318 |
assertEq(isInitialized(next), initialized); |
||
| 319 |
} |
||
| 320 |
} |
||
| 321 | |||
| 322 |
function test_fuzz_nextInitializedTickWithinOneWord_onEmptyBitmap( |
||
| 323 |
int24 tick, |
||
| 324 |
int24 tickSpacing, |
||
| 325 |
uint8 nextBitPos, |
||
| 326 |
bool lte |
||
| 327 |
) public {
|
||
| 328 |
tick = int24(bound(tick, TickMath.MIN_TICK, TickMath.MAX_TICK)); |
||
| 329 |
tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); |
||
| 330 |
int24 compressed = TickBitmap.compress(tick, tickSpacing); |
||
| 331 |
if (!lte) ++compressed; |
||
| 332 |
(int16 wordPos, uint8 bitPos) = TickBitmap.position(compressed); |
||
| 333 | |||
| 334 |
if (lte) {
|
||
| 335 |
nextBitPos = uint8(bound(nextBitPos, 0, bitPos)); |
||
| 336 |
} else {
|
||
| 337 |
nextBitPos = uint8(bound(nextBitPos, bitPos, 255)); |
||
| 338 |
} |
||
| 339 |
// Choose the next initialized tick within one word at random and flip it. |
||
| 340 |
int24 nextInitializedTick = ((int24(wordPos) << 8) + int24(uint24(nextBitPos))) * tickSpacing; |
||
| 341 |
emptyBitmap.flipTick(nextInitializedTick, tickSpacing); |
||
| 342 |
(int24 next, bool initialized) = emptyBitmap.nextInitializedTickWithinOneWord(tick, tickSpacing, lte); |
||
| 343 |
assertEq(initialized, true); |
||
| 344 |
assertEq(next, nextInitializedTick); |
||
| 345 |
} |
||
| 346 | |||
| 347 |
function isInitialized(int24 tick, int24 tickSpacing) internal view returns (bool) {
|
||
| 348 |
unchecked {
|
||
| 349 |
if (tick % tickSpacing != 0) return false; |
||
| 350 |
(int16 wordPos, uint8 bitPos) = TickBitmap.position(tick / tickSpacing); |
||
| 351 |
return bitmap[wordPos] & (1 << bitPos) != 0; |
||
| 352 |
} |
||
| 353 |
} |
||
| 354 | |||
| 355 |
function isInitialized(int24 tick) internal view returns (bool) {
|
||
| 356 |
return isInitialized(tick, 1); |
||
| 357 |
} |
||
| 358 | |||
| 359 |
function flipTick(int24 tick) internal {
|
||
| 360 |
bitmap.flipTick(tick, 1); |
||
| 361 |
} |
||
| 362 |
} |
||
| 363 |
| Lines covered: | 0 / 89 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 5 |
import {Test} from "forge-std/Test.sol";
|
||
| 6 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 7 |
import {TickMathTest} from "src/test/TickMathTest.sol";
|
||
| 8 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 9 |
import {JavascriptFfi} from "test/utils/JavascriptFfi.sol";
|
||
| 10 | |||
| 11 |
contract TickMathTestTest is Test, JavascriptFfi, GasSnapshot {
|
||
| 12 |
int24 constant MIN_TICK = -887272; |
||
| 13 |
int24 constant MAX_TICK = -MIN_TICK; |
||
| 14 | |||
| 15 |
uint160 constant MIN_SQRT_PRICE = 4295128739; |
||
| 16 |
uint160 constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342; |
||
| 17 | |||
| 18 |
uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336; |
||
| 19 | |||
| 20 |
uint256 constant ONE_PIP = 1e6; |
||
| 21 | |||
| 22 |
uint160[] getSqrtPriceAtTickFuzzResults; |
||
| 23 |
int24[] getTickAtSqrtPriceFuzzResults; |
||
| 24 | |||
| 25 |
TickMathTest tickMath; |
||
| 26 | |||
| 27 |
function setUp() public {
|
||
| 28 |
tickMath = new TickMathTest(); |
||
| 29 |
delete getSqrtPriceAtTickFuzzResults; |
||
| 30 |
delete getTickAtSqrtPriceFuzzResults; |
||
| 31 |
} |
||
| 32 | |||
| 33 |
function test_MIN_TICK_equalsNegativeMAX_TICK() public view {
|
||
| 34 |
// this invariant is required in the Tick#tickSpacingToMaxLiquidityPerTick formula |
||
| 35 |
int24 minTick = tickMath.MIN_TICK(); |
||
| 36 |
assertEq(minTick, tickMath.MAX_TICK() * -1); |
||
| 37 |
assertEq(minTick, MIN_TICK); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function test_MAX_TICK_equalsNegativeMIN_TICK() public view {
|
||
| 41 |
// this invariant is required in the Tick#tickSpacingToMaxLiquidityPerTick formula |
||
| 42 |
// this test is redundant with the above MIN_TICK test |
||
| 43 |
int24 maxTick = tickMath.MAX_TICK(); |
||
| 44 |
assertEq(maxTick, tickMath.MIN_TICK() * -1); |
||
| 45 |
assertEq(maxTick, MAX_TICK); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function test_getSqrtPriceAtTick_throwsForInt24Min() public {
|
||
| 49 |
int24 tick = type(int24).min; |
||
| 50 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick)); |
||
| 51 |
tickMath.getSqrtPriceAtTick(tick); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
function test_getSqrtPriceAtTick_throwsForTooLow() public {
|
||
| 55 |
int24 tick = MIN_TICK - 1; |
||
| 56 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick)); |
||
| 57 |
tickMath.getSqrtPriceAtTick(tick); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function test_getSqrtPriceAtTick_throwsForTooHigh() public {
|
||
| 61 |
int24 tick = MAX_TICK + 1; |
||
| 62 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick)); |
||
| 63 |
tickMath.getSqrtPriceAtTick(tick); |
||
| 64 |
} |
||
| 65 | |||
| 66 |
function test_fuzz_getSqrtPriceAtTick_throwsForTooLarge(int24 tick) public {
|
||
| 67 |
if (tick > 0) {
|
||
| 68 |
tick = int24(bound(tick, MAX_TICK + 1, type(int24).max)); |
||
| 69 |
} else {
|
||
| 70 |
tick = int24(bound(tick, type(int24).min, MIN_TICK - 1)); |
||
| 71 |
} |
||
| 72 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick)); |
||
| 73 |
tickMath.getSqrtPriceAtTick(tick); |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function test_getSqrtPriceAtTick_isValidMinTick() public view {
|
||
| 77 |
assertEq(tickMath.getSqrtPriceAtTick(MIN_TICK), tickMath.MIN_SQRT_PRICE()); |
||
| 78 |
assertEq(tickMath.getSqrtPriceAtTick(MIN_TICK), 4295128739); |
||
| 79 |
} |
||
| 80 | |||
| 81 |
function test_getSqrtPriceAtTick_isValidMinTickAddOne() public view {
|
||
| 82 |
assertEq(tickMath.getSqrtPriceAtTick(MIN_TICK + 1), 4295343490); |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function test_getSqrtPriceAtTick_isValidMaxTick() public view {
|
||
| 86 |
assertEq(tickMath.getSqrtPriceAtTick(MAX_TICK), tickMath.MAX_SQRT_PRICE()); |
||
| 87 |
assertEq(tickMath.getSqrtPriceAtTick(MAX_TICK), 1461446703485210103287273052203988822378723970342); |
||
| 88 |
} |
||
| 89 | |||
| 90 |
function test_getSqrtPriceAtTick_isValidMaxTickSubOne() public view {
|
||
| 91 |
assertEq(tickMath.getSqrtPriceAtTick(MAX_TICK - 1), 1461373636630004318706518188784493106690254656249); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function test_getSqrtPriceAtTick_isLessThanJSImplMinTick() public view {
|
||
| 95 |
// sqrt(1 / 2 ** 127) * 2 ** 96 |
||
| 96 |
uint160 jsMinSqrtPrice = 6085630636; |
||
| 97 |
uint160 solMinSqrtPrice = tickMath.getSqrtPriceAtTick(MIN_TICK); |
||
| 98 |
assertLt(solMinSqrtPrice, jsMinSqrtPrice); |
||
| 99 |
} |
||
| 100 | |||
| 101 |
function test_getSqrtPriceAtTick_isGreaterThanJSImplMaxTick() public view {
|
||
| 102 |
// sqrt(2 ** 127) * 2 ** 96 |
||
| 103 |
uint160 jsMaxSqrtPrice = 1033437718471923706666374484006904511252097097914; |
||
| 104 |
uint160 solMaxSqrtPrice = tickMath.getSqrtPriceAtTick(MAX_TICK); |
||
| 105 |
assertGt(solMaxSqrtPrice, jsMaxSqrtPrice); |
||
| 106 |
} |
||
| 107 | |||
| 108 |
function test_getTickAtSqrtPrice_throwsForTooLow() public {
|
||
| 109 |
uint160 sqrtPriceX96 = MIN_SQRT_PRICE - 1; |
||
| 110 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96)); |
||
| 111 |
tickMath.getTickAtSqrtPrice(sqrtPriceX96); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function test_getTickAtSqrtPrice_throwsForTooHigh() public {
|
||
| 115 |
uint160 sqrtPriceX96 = MAX_SQRT_PRICE; |
||
| 116 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96)); |
||
| 117 |
tickMath.getTickAtSqrtPrice(sqrtPriceX96); |
||
| 118 |
} |
||
| 119 | |||
| 120 |
function test_fuzz_getTickAtSqrtPrice_throwsForInvalid(uint160 sqrtPriceX96, bool gte) public {
|
||
| 121 |
if (gte) {
|
||
| 122 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, MAX_SQRT_PRICE, type(uint160).max)); |
||
| 123 |
} else {
|
||
| 124 |
sqrtPriceX96 = uint160(bound(sqrtPriceX96, 0, MIN_SQRT_PRICE - 1)); |
||
| 125 |
} |
||
| 126 |
vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96)); |
||
| 127 |
tickMath.getTickAtSqrtPrice(sqrtPriceX96); |
||
| 128 |
} |
||
| 129 | |||
| 130 |
function test_getTickAtSqrtPrice_isValidMinSqrtPrice() public view {
|
||
| 131 |
assertEq(tickMath.getTickAtSqrtPrice(MIN_SQRT_PRICE), MIN_TICK); |
||
| 132 |
} |
||
| 133 | |||
| 134 |
function test_getTickAtSqrtPrice_isValidMinSqrtPricePlusOne() public view {
|
||
| 135 |
assertEq(tickMath.getTickAtSqrtPrice(4295343490), MIN_TICK + 1); |
||
| 136 |
} |
||
| 137 | |||
| 138 |
function test_getTickAtSqrtPrice_isValidPriceClosestToMaxTick() public view {
|
||
| 139 |
assertEq(tickMath.getTickAtSqrtPrice(MAX_SQRT_PRICE - 1), MAX_TICK - 1); |
||
| 140 |
} |
||
| 141 | |||
| 142 |
function test_getTickAtSqrtPrice_isValidMaxSqrtPriceMinusOne() public view {
|
||
| 143 |
assertEq(tickMath.getTickAtSqrtPrice(1461373636630004318706518188784493106690254656249), MAX_TICK - 1); |
||
| 144 |
} |
||
| 145 | |||
| 146 |
function test_getSqrtPriceAtTick_matchesJavaScriptImplByOneHundrethOfABip() public {
|
||
| 147 |
string memory jsParameters = ""; |
||
| 148 | |||
| 149 |
int24 tick = 50; |
||
| 150 | |||
| 151 |
while (true) {
|
||
| 152 |
if (tick > MAX_TICK) break; |
||
| 153 |
// test negative and positive tick |
||
| 154 |
for (uint256 i = 0; i < 2; i++) {
|
||
| 155 |
tick = tick * -1; |
||
| 156 |
if (tick != -50) jsParameters = string(abi.encodePacked(jsParameters, ",")); // do not leave comma in front of first number |
||
| 157 |
// add tick to javascript parameters to be calculated inside script |
||
| 158 |
jsParameters = string(abi.encodePacked(jsParameters, vm.toString(int256(tick)))); |
||
| 159 |
// track solidity result for tick |
||
| 160 |
getSqrtPriceAtTickFuzzResults.push(tickMath.getSqrtPriceAtTick(tick)); |
||
| 161 |
} |
||
| 162 |
tick = tick * 2; |
||
| 163 |
} |
||
| 164 | |||
| 165 |
bytes memory jsResult = runScript("forge-test-getSqrtPriceAtTick", jsParameters);
|
||
| 166 |
uint160[] memory jsSqrtPrices = abi.decode(jsResult, (uint160[])); |
||
| 167 | |||
| 168 |
for (uint256 i = 0; i < jsSqrtPrices.length; i++) {
|
||
| 169 |
uint160 jsSqrtPrice = jsSqrtPrices[i]; |
||
| 170 |
uint160 solResult = getSqrtPriceAtTickFuzzResults[i]; |
||
| 171 |
(uint160 gtResult, uint160 ltResult) = |
||
| 172 |
jsSqrtPrice > solResult ? (jsSqrtPrice, solResult) : (solResult, jsSqrtPrice); |
||
| 173 |
uint160 resultsDiff = gtResult - ltResult; |
||
| 174 | |||
| 175 |
// assert solc/js result is at most off by 1/100th of a bip (aka one pip) |
||
| 176 |
assertEq(resultsDiff * ONE_PIP / jsSqrtPrice, 0); |
||
| 177 |
} |
||
| 178 |
} |
||
| 179 | |||
| 180 |
function test_getTickAtSqrtPrice_matchesJavascriptImplWithin1() public {
|
||
| 181 |
string memory jsParameters = ""; |
||
| 182 | |||
| 183 |
uint160 sqrtPrice = MIN_SQRT_PRICE; |
||
| 184 |
unchecked {
|
||
| 185 |
while (sqrtPrice < sqrtPrice * 16) {
|
||
| 186 |
if (sqrtPrice != MIN_SQRT_PRICE) jsParameters = string(abi.encodePacked(jsParameters, ",")); // do not leave comma in front of first number |
||
| 187 |
// add tick to javascript parameters to be calculated inside script |
||
| 188 |
jsParameters = string(abi.encodePacked(jsParameters, vm.toString(sqrtPrice))); |
||
| 189 |
// track solidity result for sqrtPrice |
||
| 190 |
getTickAtSqrtPriceFuzzResults.push(tickMath.getTickAtSqrtPrice(sqrtPrice)); |
||
| 191 |
sqrtPrice = sqrtPrice * 16; |
||
| 192 |
} |
||
| 193 |
} |
||
| 194 | |||
| 195 |
bytes memory jsResult = runScript("forge-test-getTickAtSqrtPrice", jsParameters);
|
||
| 196 |
int24[] memory jsTicks = abi.decode(jsResult, (int24[])); |
||
| 197 | |||
| 198 |
for (uint256 i = 0; i < jsTicks.length; i++) {
|
||
| 199 |
int24 jsTick = jsTicks[i]; |
||
| 200 |
int24 solTick = getTickAtSqrtPriceFuzzResults[i]; |
||
| 201 | |||
| 202 |
(int24 gtResult, int24 ltResult) = jsTick > solTick ? (jsTick, solTick) : (solTick, jsTick); |
||
| 203 |
int24 resultsDiff = gtResult - ltResult; |
||
| 204 |
assertLt(resultsDiff, 2); |
||
| 205 |
} |
||
| 206 |
} |
||
| 207 | |||
| 208 |
/// @notice Benchmark the gas cost of `getSqrtPriceAtTick` |
||
| 209 |
function test_getSqrtPriceAtTick_gasCost() public {
|
||
| 210 |
snapStart("TickMathGetSqrtPriceAtTick");
|
||
| 211 |
unchecked {
|
||
| 212 |
for (int24 tick = -50; tick < 50;) {
|
||
| 213 |
TickMath.getSqrtPriceAtTick(tick++); |
||
| 214 |
} |
||
| 215 |
} |
||
| 216 |
snapEnd(); |
||
| 217 |
} |
||
| 218 | |||
| 219 |
/// @notice Benchmark the gas cost of `getTickAtSqrtPrice` |
||
| 220 |
function test_getTickAtSqrtPrice_gasCost() public {
|
||
| 221 |
snapStart("TickMathGetTickAtSqrtPrice");
|
||
| 222 |
unchecked {
|
||
| 223 |
uint160 sqrtPriceX96 = 1 << 33; |
||
| 224 |
for (uint256 i; i++ < 100; sqrtPriceX96 <<= 1) {
|
||
| 225 |
TickMath.getTickAtSqrtPrice(sqrtPriceX96); |
||
| 226 |
} |
||
| 227 |
} |
||
| 228 |
snapEnd(); |
||
| 229 |
} |
||
| 230 |
} |
||
| 231 |
| Lines covered: | 0 / 15 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {UnsafeMath} from "../../src/libraries/UnsafeMath.sol";
|
||
| 6 | |||
| 7 |
contract UnsafeMathTest is Test {
|
||
| 8 |
using UnsafeMath for uint256; |
||
| 9 | |||
| 10 |
uint256 constant Q128 = 2 ** 128; |
||
| 11 |
uint256 constant MAX_UINT256 = type(uint256).max; |
||
| 12 | |||
| 13 |
function test_divRoundingUp_zeroDoesNotRevert(uint256 x) public pure {
|
||
| 14 |
x.divRoundingUp(0); |
||
| 15 |
} |
||
| 16 | |||
| 17 |
function test_divRoundingUp_maxInput() public pure {
|
||
| 18 |
assertEq(MAX_UINT256.divRoundingUp(MAX_UINT256), 1); |
||
| 19 |
} |
||
| 20 | |||
| 21 |
function test_divRoundingUp_RoundsUp() public pure {
|
||
| 22 |
uint256 result = Q128 / 3 + 1; |
||
| 23 |
assertEq(Q128.divRoundingUp(3), result); |
||
| 24 |
} |
||
| 25 | |||
| 26 |
function test_fuzz_divRoundingUp(uint256 x, uint256 y) public pure {
|
||
| 27 |
vm.assume(y != 0); |
||
| 28 |
uint256 result = x.divRoundingUp(y); |
||
| 29 |
assertTrue(result == x / y || result == x / y + 1); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function test_invariant_divRoundingUp(uint256 x, uint256 y) public pure {
|
||
| 33 |
vm.assume(y != 0); |
||
| 34 |
uint256 z = x.divRoundingUp(y); |
||
| 35 |
uint256 diff = z - (x / y); |
||
| 36 |
if (x % y == 0) {
|
||
| 37 |
assertEq(diff, 0); |
||
| 38 |
} else {
|
||
| 39 |
assertEq(diff, 1); |
||
| 40 |
} |
||
| 41 |
} |
||
| 42 |
} |
||
| 43 |
| Lines covered: | 0 / 136 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import "forge-std/Base.sol"; |
||
| 5 | |||
| 6 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 7 | |||
| 8 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 9 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 10 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 11 | |||
| 12 |
import {Pool} from "src/libraries/Pool.sol";
|
||
| 13 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 16 | |||
| 17 |
import {Actions, ActionsRouter} from "src/test/ActionsRouter.sol";
|
||
| 18 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 19 |
import {PropertiesAsserts} from "test/trailofbits/PropertiesHelper.sol";
|
||
| 20 |
import {V4StateMachine} from "test/trailofbits/V4StateMachine.sol";
|
||
| 21 |
import {ShadowAccounting} from "test/trailofbits/ShadowAccounting.sol";
|
||
| 22 | |||
| 23 | |||
| 24 |
enum ActionCallbacks {
|
||
| 25 |
BEFORE_DONATE, |
||
| 26 |
AFTER_DONATE, |
||
| 27 |
BEFORE_INITIALIZE, |
||
| 28 |
AFTER_INITIALIZE, |
||
| 29 |
BEFORE_SWAP, |
||
| 30 |
AFTER_SWAP, |
||
| 31 |
BEFORE_MODIFY_POSITION, |
||
| 32 |
AFTER_MODIFY_POSITION, |
||
| 33 |
BEFORE_TAKE, |
||
| 34 |
AFTER_TAKE, |
||
| 35 |
BEFORE_SETTLE, |
||
| 36 |
AFTER_SETTLE, |
||
| 37 |
BEFORE_SETTLE_NATIVE, |
||
| 38 |
AFTER_SETTLE_NATIVE, |
||
| 39 |
BEFORE_MINT, |
||
| 40 |
AFTER_MINT, |
||
| 41 |
BEFORE_BURN, |
||
| 42 |
AFTER_BURN, |
||
| 43 |
BEFORE_CLEAR, |
||
| 44 |
AFTER_CLEAR, |
||
| 45 |
BEFORE_SYNC, |
||
| 46 |
AFTER_SYNC, |
||
| 47 |
SHORTCUT_SETTLE, |
||
| 48 |
SET_NEW_PROTOCOL_FEE, |
||
| 49 |
COLLECT_PROTOCOL_FEES, |
||
| 50 |
AFTER_TRANSFER_FROM |
||
| 51 |
} |
||
| 52 | |||
| 53 | |||
| 54 |
contract ActionFuzzBase is V4StateMachine, ShadowAccounting, ScriptBase {
|
||
| 55 |
using TransientStateLibrary for IPoolManager; |
||
| 56 |
using PoolIdLibrary for PoolKey; |
||
| 57 | |||
| 58 |
PoolKey[] public DeployedPools; |
||
| 59 |
mapping(PoolId => bool) PoolInitialized; |
||
| 60 |
Currency[] public Currencies; |
||
| 61 | |||
| 62 | |||
| 63 |
// The fuzzer calls add<X> functions to add actions to the sequence with their corresponding parameters. |
||
| 64 |
Actions[] actions; |
||
| 65 |
bytes[] params; |
||
| 66 | |||
| 67 |
// We'll use these to "cache" sequences so we can run through multiple unlock/lock contexts in a single tx. |
||
| 68 |
// This might help sus out issues related to clearing transient storage. |
||
| 69 |
Actions[][] actionSequences; |
||
| 70 |
bytes[][] paramSequences; |
||
| 71 | |||
| 72 |
uint public NUMBER_CURRENCIES = 6; |
||
| 73 | |||
| 74 |
constructor() payable {
|
||
| 75 |
Deployers.deployFreshManagerAndRouters(); |
||
| 76 |
// Initialize currencies |
||
| 77 |
for (uint i = 0; i < NUMBER_CURRENCIES; i++) {
|
||
| 78 |
// we place the native currency at the end of our currencies array to protect the existing corpus. |
||
| 79 |
if (i == NUMBER_CURRENCIES-1) {
|
||
| 80 |
Currencies.push(CurrencyLibrary.NATIVE); |
||
| 81 |
} else {
|
||
| 82 |
Currency c = deployMintAndApproveCurrency(); |
||
| 83 |
Currencies.push(c); |
||
| 84 |
} |
||
| 85 |
} |
||
| 86 |
} |
||
| 87 | |||
| 88 |
function getActionRouter() public view returns (address) {
|
||
| 89 |
return address(actionsRouter); |
||
| 90 |
} |
||
| 91 | |||
| 92 |
function getManager() public view returns (address) {
|
||
| 93 |
return address(manager); |
||
| 94 |
} |
||
| 95 | |||
| 96 | |||
| 97 |
function runActions() public {
|
||
| 98 |
// start running actions from our stored sequences |
||
| 99 |
for(uint i=0; i<actionSequences.length; i++) {
|
||
| 100 |
Actions[] memory a = actionSequences[i]; |
||
| 101 |
bytes[] memory p = paramSequences[i]; |
||
| 102 |
actionsRouter.executeActions(a, p); |
||
| 103 |
|
||
| 104 |
// UNI-E2E-1 |
||
| 105 |
assertEq(OutstandingDeltas, 0, "Outstanding deltas must be zero after the singleton is re-locked."); |
||
| 106 |
} |
||
| 107 | |||
| 108 |
// run whatever's in the current sequence |
||
| 109 |
actionsRouter.executeActions(actions, params); |
||
| 110 | |||
| 111 |
// UNI-E2E-1 |
||
| 112 |
assertEq(OutstandingDeltas, 0, "Outstanding deltas must be zero after the singleton is re-locked."); |
||
| 113 |
_coverageNudge(); |
||
| 114 |
delete actions; |
||
| 115 |
delete params; |
||
| 116 |
delete actionSequences; |
||
| 117 |
delete paramSequences; |
||
| 118 |
_clearTransientRemittances(); |
||
| 119 |
emit LogString("pool key");
|
||
| 120 |
if(DeployedPools.length > 0) {
|
||
| 121 |
emit LogBytes("poolId", abi.encode(DeployedPools[0].toId()));
|
||
| 122 |
} |
||
| 123 |
} |
||
| 124 | |||
| 125 |
function prepareNewLock() public {
|
||
| 126 |
// store the current sequence |
||
| 127 |
actionSequences.push(actions); |
||
| 128 |
paramSequences.push(params); |
||
| 129 |
delete actions; |
||
| 130 |
delete params; |
||
| 131 |
} |
||
| 132 | |||
| 133 | |||
| 134 |
function _coverageNudge() internal {
|
||
| 135 |
for(uint i=0; i<actions.length; i++){
|
||
| 136 |
if(actions[i] == Actions.SETTLE){
|
||
| 137 |
emit LogString("We did a SETTLE and it worked!");
|
||
| 138 |
} else if (actions[i] == Actions.SETTLE_NATIVE){
|
||
| 139 |
emit LogString("We did a SETTLE_NATIVE and it worked!");
|
||
| 140 |
} else if (actions[i] == Actions.SETTLE_FOR){
|
||
| 141 |
emit LogString("We did a SETTLE_FOR and it worked!");
|
||
| 142 |
} else if (actions[i] == Actions.TAKE){
|
||
| 143 |
emit LogString("We did a TAKE and it worked!");
|
||
| 144 |
} else if (actions[i] == Actions.SYNC){
|
||
| 145 |
emit LogString("We did a SYNC and it worked!");
|
||
| 146 |
} else if (actions[i] == Actions.MINT){
|
||
| 147 |
emit LogString("We did a MINT and it worked!");
|
||
| 148 |
} else if (actions[i] == Actions.BURN){
|
||
| 149 |
emit LogString("We did a BURN and it worked!");
|
||
| 150 |
} else if (actions[i] == Actions.CLEAR){
|
||
| 151 |
emit LogString("We did a CLEAR and it worked!");
|
||
| 152 |
} else if (actions[i] == Actions.TRANSFER_FROM){
|
||
| 153 |
emit LogString("We did a TRANSFER_FROM and it worked!");
|
||
| 154 |
} else if (actions[i] == Actions.INITIALIZE){
|
||
| 155 |
emit LogString("We did a INITIALIZE and it worked!");
|
||
| 156 |
} else if (actions[i] == Actions.DONATE){
|
||
| 157 |
emit LogString("We did a DONATE and it worked!");
|
||
| 158 |
} else if (actions[i] == Actions.MODIFY_POSITION){
|
||
| 159 |
emit LogString("We did a MODIFY_POSITION and it worked!");
|
||
| 160 |
} else if (actions[i] == Actions.SWAP){
|
||
| 161 |
emit LogString("We did a SWAP and it worked!");
|
||
| 162 |
} else if (actions[i] == Actions.HARNESS_CALLBACK){
|
||
| 163 |
emit LogString("We did a HARNESS_CALLBACK and it worked!");
|
||
| 164 |
} |
||
| 165 |
} |
||
| 166 |
} |
||
| 167 | |||
| 168 |
function _encodeHarnessCallback(ActionCallbacks cbType, bytes memory cbParams) internal view returns (bytes memory) {
|
||
| 169 |
bytes memory harnessCbParamEncoded = abi.encode( |
||
| 170 |
cbType, |
||
| 171 |
cbParams |
||
| 172 |
); |
||
| 173 |
|
||
| 174 |
return abi.encode( |
||
| 175 |
address(this), |
||
| 176 |
harnessCbParamEncoded |
||
| 177 |
); |
||
| 178 |
} |
||
| 179 | |||
| 180 |
/// @notice While this function calls it a "clamp", we're technically using modulo so our input space is evenly distributed. |
||
| 181 |
function _clampToUsableTicks(int24 minTick, int24 maxTick, PoolKey memory poolKey) internal returns (int24, int24) {
|
||
| 182 |
int24 minUsableTick = TickMath.minUsableTick(poolKey.tickSpacing); |
||
| 183 |
int24 maxUsableTick = TickMath.maxUsableTick(poolKey.tickSpacing); |
||
| 184 | |||
| 185 |
emit LogInt256("minUsableTick", minUsableTick);
|
||
| 186 |
emit LogInt256("maxUsableTick", maxUsableTick);
|
||
| 187 | |||
| 188 |
minTick = int24(clampBetween(minTick, minUsableTick, maxUsableTick)); |
||
| 189 |
maxTick = int24(clampBetween(maxTick, minUsableTick, maxUsableTick)); |
||
| 190 | |||
| 191 |
if (maxTick < minTick) {
|
||
| 192 |
int24 tmp = minTick; |
||
| 193 |
minTick = maxTick; |
||
| 194 |
maxTick = tmp; |
||
| 195 |
} |
||
| 196 | |||
| 197 |
emit LogInt256("minTick", minTick);
|
||
| 198 |
emit LogInt256("maxTick", maxTick);
|
||
| 199 |
return (minTick, maxTick); |
||
| 200 |
} |
||
| 201 | |||
| 202 |
/// @notice While this function calls it a "clamp", we're technically using modulo so our input space is evenly distributed. |
||
| 203 |
function _clampToValidCurrencies(uint8 currency1I, uint8 currency2I) internal returns (Currency, Currency) {
|
||
| 204 |
uint c1 = clampBetween(currency1I, 0, NUMBER_CURRENCIES-1); |
||
| 205 |
uint c2 = clampBetween(currency2I, 0, NUMBER_CURRENCIES-1); |
||
| 206 |
require(c1 != c2); |
||
| 207 | |||
| 208 |
Currency cur1 = Currencies[c1]; |
||
| 209 |
Currency cur2 = Currencies[c2]; |
||
| 210 |
if (cur1 >= cur2) {
|
||
| 211 |
emit LogAddress("address 1", address(Currency.unwrap(cur2)));
|
||
| 212 |
emit LogAddress("address 2", address(Currency.unwrap(cur1)));
|
||
| 213 |
return (cur2, cur1); |
||
| 214 |
} else {
|
||
| 215 |
emit LogAddress("address 1", address(Currency.unwrap(cur1)));
|
||
| 216 |
emit LogAddress("address 2", address(Currency.unwrap(cur2)));
|
||
| 217 |
return (cur1, cur2); |
||
| 218 |
} |
||
| 219 |
} |
||
| 220 | |||
| 221 |
/// @notice While this function calls it a "clamp", we're technically using modulo so our input space is evenly distributed. |
||
| 222 |
function _clampToValidPool(uint poolIndex) internal returns ( PoolKey memory) {
|
||
| 223 |
poolIndex = clampBetween(poolIndex, 0, DeployedPools.length-1); |
||
| 224 |
emit LogUint256("Pool index", poolIndex);
|
||
| 225 |
return DeployedPools[poolIndex]; |
||
| 226 |
} |
||
| 227 | |||
| 228 | |||
| 229 |
/* Functions we want as an entrypoint for fuzzing, but do not verify properties for. */ |
||
| 230 |
function addTransferFrom(uint8 currency1I, uint256 amount, address from, address to) public {
|
||
| 231 |
Currency c1 = Currencies[clampBetween(currency1I, 0, NUMBER_CURRENCIES-1)]; |
||
| 232 |
bytes memory param = abi.encode(c1, from, to, amount); |
||
| 233 |
actions.push(Actions.TRANSFER_FROM); |
||
| 234 |
params.push(param); |
||
| 235 | |||
| 236 |
bytes memory cbParams = abi.encode(c1, amount, from, to); |
||
| 237 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 238 |
params.push(_encodeHarnessCallback(ActionCallbacks.AFTER_TRANSFER_FROM, cbParams)); |
||
| 239 |
} |
||
| 240 | |||
| 241 |
function _afterTransferFrom(Currency c, uint256 amount, address, address to) internal {
|
||
| 242 |
if(c == RemittanceCurrency && to == address(manager)) {
|
||
| 243 |
RemittanceAmount += int256(amount); |
||
| 244 |
} |
||
| 245 |
} |
||
| 246 | |||
| 247 |
/// @notice This function is used to verify various properties that should hold at all times while the singleton is unlocked. |
||
| 248 |
/// When fuzzing a new action, only call _verifyGlobalProperties after doing accounting for our copy of currency deltas, |
||
| 249 |
/// liquidity, etc. |
||
| 250 |
/// It may make more sense for this to live in ShadowAccounting. |
||
| 251 |
function _verifyGlobalProperties(address, Currency currency) internal {
|
||
| 252 |
// the only actor in the system we owe money to right now is address(actionsRouter). |
||
| 253 |
// if this changes, we need to sum all currency deltas of all actors, not just actionsRouter |
||
| 254 | |||
| 255 |
int256 delta = manager.currencyDelta(address(actionsRouter), currency); |
||
| 256 |
uint256 singletonBalance = currency.balanceOf(address(manager)); |
||
| 257 |
emit LogUint256("Global: singleton balance", singletonBalance);
|
||
| 258 | |||
| 259 |
uint256 singletonBalanceInclDelta; |
||
| 260 |
if(delta > 0) {
|
||
| 261 |
singletonBalanceInclDelta = singletonBalance - uint256(delta); |
||
| 262 |
} else {
|
||
| 263 |
singletonBalanceInclDelta = singletonBalance + uint256(-delta); |
||
| 264 |
} |
||
| 265 |
emit LogUint256("Global: singleton balance incl delta", singletonBalanceInclDelta);
|
||
| 266 |
emit LogUint256("Global: singleton liquidity", SingletonLiquidity[currency]);
|
||
| 267 |
emit LogUint256("Global: singleton lp fees (in fee growth)", SingletonLPFees[currency]);
|
||
| 268 |
emit LogInt256("Global: currencyDelta for actor", delta);
|
||
| 269 | |||
| 270 |
assertGte(singletonBalanceInclDelta, SingletonLiquidity[currency], "Bug in harness? Probably turn this into a property."); |
||
| 271 |
|
||
| 272 |
if (delta >= 0) {
|
||
| 273 |
// UNI-ACTION-1 (weak, no protocol fees) |
||
| 274 |
assertGte(singletonBalance - SingletonLiquidity[currency], uint256(delta), "The amount owed to an actor must always be less than or equal the balance of the singleton."); |
||
| 275 |
} |
||
| 276 |
uint256 singletonBalanceAfterRelocking = _deltaAdd(singletonBalance, -delta); |
||
| 277 | |||
| 278 |
// This amount represents the amount of currency that would be remaining in the singleton if every LPer withdrew their liquidity and fees. |
||
| 279 |
uint256 balanceAvailableForProtocolFees = singletonBalanceAfterRelocking - SingletonLiquidity[currency] - SingletonLPFees[currency]; |
||
| 280 |
uint256 protocolFees = manager.protocolFeesAccrued(currency); |
||
| 281 |
|
||
| 282 |
// UNI-ACTION-3 |
||
| 283 |
assertLte(protocolFees, balanceAvailableForProtocolFees, "The amount of protocol fees owed may not exceed the singleton's balance (less its deployed liquidity) while the currency has a positive or zero delta."); |
||
| 284 | |||
| 285 |
if (delta >= 0) {
|
||
| 286 |
uint256 balanceAvailableForCreditors = singletonBalance - protocolFees - SingletonLiquidity[currency]- SingletonLPFees[currency]; |
||
| 287 |
// UNI-ACTION-2 |
||
| 288 |
assertLte(delta, int256(balanceAvailableForCreditors), "The amount owed to an actor must always be less than or equal the balance of the singleton, less protocol fees and LP fees."); |
||
| 289 |
} |
||
| 290 |
} |
||
| 291 | |||
| 292 |
function _deltaAdd(uint256 a, int256 delta) internal returns (uint256 sum) {
|
||
| 293 |
unchecked {
|
||
| 294 |
if(delta >= 0){
|
||
| 295 |
sum = a + uint256(delta); |
||
| 296 |
assertGte(sum, a, "Sum overflow. This may be a bug in the harness, or an issue in v4."); |
||
| 297 |
} else {
|
||
| 298 |
sum = a - uint256(-delta); |
||
| 299 |
assertLt(sum, a, "Sum underflow. This may be a bug in the harness, or an issue in v4."); |
||
| 300 |
} |
||
| 301 |
} |
||
| 302 |
} |
||
| 303 | |||
| 304 |
fallback() external payable {}
|
||
| 305 |
} |
| Lines covered: | 142 / 170 (83.5%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 5 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 6 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 7 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 8 |
import {Position} from "src/libraries/Position.sol";
|
||
| 9 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 10 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 11 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 12 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 13 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 14 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 15 |
import {PropertiesAsserts} from "./PropertiesHelper.sol";
|
||
| 16 |
import {IProtocolFeeController} from "src/interfaces/IProtocolFeeController.sol";
|
||
| 17 |
import {Actions} from "../../src/test/ActionsRouter.sol";
|
||
| 18 |
import {IActionsHarness} from "./IActionsHarness.sol";
|
||
| 19 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 20 |
import {ActionFuzzBase, ActionCallbacks} from "./ActionFuzzBase.sol";
|
||
| 21 | |||
| 22 | |||
| 23 | |||
| 24 |
import {DonateActionProps} from "./actionprops/DonateActionProps.sol";
|
||
| 25 |
import {InitializeActionProps} from "./actionprops/InitializeActionProps.sol";
|
||
| 26 |
import {ModifyPositionActionProps} from "./actionprops/ModifyPositionActionProps.sol";
|
||
| 27 |
import {SwapActionProps} from "./actionprops/SwapActionProps.sol";
|
||
| 28 |
import {TakeActionProps} from "./actionprops/TakeActionProps.sol";
|
||
| 29 |
import {SettleActionProps} from "./actionprops/SettleActionProps.sol";
|
||
| 30 |
import {SettleNativeActionProps} from "./actionprops/SettleNativeActionProps.sol";
|
||
| 31 |
import {MintActionProps} from "./actionprops/MintActionProps.sol";
|
||
| 32 |
import {BurnActionProps} from "./actionprops/BurnActionProps.sol";
|
||
| 33 |
import {SyncActionProps} from "./actionprops/SyncActionProps.sol";
|
||
| 34 |
import {ClearActionProps} from "./actionprops/ClearActionProps.sol";
|
||
| 35 |
import {ProtocolFeeActionProps} from "./actionprops/ProtocolFeeActionProps.sol";
|
||
| 36 | |||
| 37 |
√ 200
|
contract ActionFuzzEntrypoint is |
|
| 38 |
ActionFuzzBase, |
||
| 39 |
IActionsHarness, |
||
| 40 |
DonateActionProps, |
||
| 41 |
InitializeActionProps, |
||
| 42 |
ModifyPositionActionProps, |
||
| 43 |
SwapActionProps, |
||
| 44 |
TakeActionProps, |
||
| 45 |
SettleActionProps, |
||
| 46 |
SettleNativeActionProps, |
||
| 47 |
MintActionProps, |
||
| 48 |
BurnActionProps, |
||
| 49 |
SyncActionProps, |
||
| 50 |
ClearActionProps, |
||
| 51 |
ProtocolFeeActionProps {
|
||
| 52 |
using PoolIdLibrary for PoolKey; |
||
| 53 |
using CurrencyLibrary for Currency; |
||
| 54 |
using TransientStateLibrary for IPoolManager; |
||
| 55 | |||
| 56 |
// configure harness in ActionFuzzBase.sol |
||
| 57 |
constructor() payable { }
|
||
| 58 | |||
| 59 |
function routerCallback(bytes memory data, bytes memory lastReturnData) external override {
|
||
| 60 |
√ 3
|
⟳ 3
|
(ActionCallbacks cbType, bytes memory cbData) = abi.decode(data, (ActionCallbacks, bytes)); |
| 61 | |||
| 62 |
√ 2
|
⟳ 2
|
if( cbType == ActionCallbacks.BEFORE_DONATE) {
|
| 63 |
√ 13
|
⟳ 13
|
emit LogString("before donate");
|
| 64 |
√ 2
|
⟳ 2
|
_beforeDonate(cbData); |
| 65 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_DONATE) {
|
| 66 |
√ 13
|
⟳ 13
|
emit LogString("after donate");
|
| 67 |
√ 2
|
⟳ 2
|
BalanceDelta bd = abi.decode(lastReturnData, (BalanceDelta)); |
| 68 |
√ 2
|
⟳ 2
|
_afterDonate(bd); |
| 69 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_SWAP) {
|
| 70 |
√ 13
|
⟳ 13
|
emit LogString("before swap");
|
| 71 |
√ 2
|
⟳ 2
|
_beforeSwap(cbData); |
| 72 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_SWAP) {
|
| 73 |
√ 13
|
⟳ 13
|
emit LogString("after swap");
|
| 74 |
√ 2
|
⟳ 2
|
_afterSwap(abi.decode(lastReturnData, (BalanceDelta))); |
| 75 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_MODIFY_POSITION) {
|
| 76 |
√ 13
|
⟳ 13
|
emit LogString("before modify position");
|
| 77 |
√ 2
|
⟳ 2
|
_beforeModifyPosition(cbData); |
| 78 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_MODIFY_POSITION) {
|
| 79 |
√ 13
|
⟳ 13
|
emit LogString("after modify position");
|
| 80 |
√ 3
|
⟳ 3
|
(BalanceDelta b1, BalanceDelta b2) = abi.decode(lastReturnData, (BalanceDelta,BalanceDelta)); |
| 81 |
√ 3
|
⟳ 3
|
_afterModifyPosition(b1, b2); |
| 82 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_TAKE) {
|
| 83 |
√ 13
|
⟳ 13
|
emit LogString("before take");
|
| 84 |
√ 2
|
⟳ 2
|
_beforeTake(cbData); |
| 85 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_TAKE) {
|
| 86 |
√ 13
|
⟳ 13
|
emit LogString("after take");
|
| 87 |
√ 1
|
⟳ 1
|
_afterTake(); |
| 88 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_SETTLE) {
|
| 89 |
√ 13
|
⟳ 13
|
emit LogString("before settle");
|
| 90 |
√ 2
|
⟳ 2
|
_beforeSettle(cbData); |
| 91 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_SETTLE) {
|
| 92 |
√ 13
|
⟳ 13
|
emit LogString("after settle");
|
| 93 |
√ 2
|
⟳ 2
|
uint256 paid = abi.decode(lastReturnData, (uint256)); |
| 94 |
√ 2
|
⟳ 2
|
_afterSettle(paid); |
| 95 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.SHORTCUT_SETTLE) {
|
| 96 |
√ 13
|
⟳ 13
|
emit LogString("shortcut settle");
|
| 97 |
√ 2
|
⟳ 2
|
_shortcutSettle(abi.decode(cbData, (address))); |
| 98 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_SETTLE_NATIVE) {
|
| 99 |
√ 13
|
⟳ 13
|
emit LogString("before settle native");
|
| 100 |
√ 2
|
⟳ 2
|
_beforeSettleNative(cbData); |
| 101 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_SETTLE_NATIVE) {
|
| 102 |
√ 13
|
⟳ 13
|
emit LogString("after settle native");
|
| 103 |
√ 2
|
⟳ 2
|
uint256 paid = abi.decode(lastReturnData, (uint256)); |
| 104 |
√ 2
|
⟳ 2
|
_afterSettleNative(paid); |
| 105 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_MINT) {
|
| 106 |
√ 13
|
⟳ 13
|
emit LogString("before mint");
|
| 107 |
√ 2
|
⟳ 2
|
_beforeMint(cbData); |
| 108 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_MINT) {
|
| 109 |
√ 13
|
⟳ 13
|
emit LogString("after mint");
|
| 110 |
√ 1
|
⟳ 1
|
_afterMint(); |
| 111 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_BURN) {
|
| 112 |
√ 13
|
⟳ 13
|
emit LogString("before burn");
|
| 113 |
√ 2
|
⟳ 2
|
_beforeBurn(cbData); |
| 114 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_BURN) {
|
| 115 |
√ 13
|
⟳ 13
|
emit LogString("after burn");
|
| 116 |
√ 1
|
⟳ 1
|
_afterBurn(); |
| 117 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_SYNC) {
|
| 118 |
√ 13
|
⟳ 13
|
emit LogString("before sync");
|
| 119 |
√ 2
|
⟳ 2
|
_beforeSync(cbData); |
| 120 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_SYNC) {
|
| 121 |
√ 13
|
⟳ 13
|
emit LogString("after sync");
|
| 122 |
√ 1
|
⟳ 1
|
_afterSync(); |
| 123 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.BEFORE_CLEAR) {
|
| 124 |
√ 13
|
⟳ 13
|
emit LogString("before clear");
|
| 125 |
√ 2
|
⟳ 2
|
_beforeClear(cbData); |
| 126 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_CLEAR) {
|
| 127 |
√ 13
|
⟳ 13
|
emit LogString("after clear");
|
| 128 |
√ 1
|
⟳ 1
|
_afterClear(); |
| 129 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.SET_NEW_PROTOCOL_FEE) {
|
| 130 |
√ 13
|
⟳ 13
|
emit LogString("set new protocol fee");
|
| 131 |
√ 2
|
⟳ 2
|
_setNewProtocolFee(cbData); |
| 132 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.COLLECT_PROTOCOL_FEES) {
|
| 133 |
√ 13
|
⟳ 13
|
emit LogString("collect protocol fees");
|
| 134 |
√ 2
|
⟳ 2
|
_collectProtocolFees(cbData); |
| 135 |
√ 2
|
⟳ 2
|
} else if (cbType == ActionCallbacks.AFTER_TRANSFER_FROM) {
|
| 136 |
√ 5
|
⟳ 5
|
(Currency c, uint256 amount, address from, address to) = abi.decode(cbData, (Currency, uint256, address, address)); |
| 137 |
√ 13
|
⟳ 13
|
emit LogString("after transfer from");
|
| 138 |
√ 5
|
⟳ 5
|
_afterTransferFrom(c, amount, from, to); |
| 139 |
} else {
|
||
| 140 |
assertWithMsg(false, "unknown callback action"); |
||
| 141 |
} |
||
| 142 |
} |
||
| 143 | |||
| 144 | |||
| 145 |
function updatePoolDynamicLpFee(uint8 poolIdx, uint24 fee) public {
|
||
| 146 |
⟳ 3
|
PoolKey memory poolKey = _clampToValidPool(poolIdx); |
|
| 147 |
⟳ 7
|
manager.updateDynamicLPFee(poolKey, fee); |
|
| 148 |
emit LogUint256("modified pool's dynamic fee to ", fee);
|
||
| 149 |
} |
||
| 150 | |||
| 151 |
/* The following functions act as "shortcuts" and give the fuzzer a better chance of creating a valid runActions sequence. */ |
||
| 152 | |||
| 153 |
/// @notice This function eases coverage generation by adding a new pool and initializing it |
||
| 154 |
function addInitializeAndAddLiquidity(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee, int24 minTick, int24 maxTick, int128 liqDelta, uint256 salt) public {
|
||
| 155 |
√ 6
|
⟳ 6
|
addInitialize(currency1I, currency2I, tickSpacing, startPrice, fee); |
| 156 |
√ 5
|
⟳ 5
|
uint poolIdx = DeployedPools.length-1; |
| 157 |
√ 1
|
⟳ 1
|
emit LogUint256("poolidx", poolIdx);
|
| 158 |
√ 6
|
⟳ 6
|
addModifyPosition(uint8(poolIdx), minTick, maxTick, liqDelta, salt); |
| 159 |
} |
||
| 160 | |||
| 161 |
/// @notice Doing everything addInitializeAndAddLiquidity does & settle the deltas. |
||
| 162 |
function addInitializeAndAddLiquidityAndSettle(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee, int24 minTick, int24 maxTick, int128 liqDelta, uint256 salt) public {
|
||
| 163 |
√ 10
|
⟳ 10
|
addInitializeAndAddLiquidity(currency1I, currency2I, tickSpacing, startPrice, fee, minTick, maxTick, liqDelta, salt); |
| 164 |
√ 1
|
⟳ 1
|
runActionsWithShortcutSettle(); |
| 165 |
} |
||
| 166 | |||
| 167 |
/// @notice Swap into and out of a pair, then settling the deltas. |
||
| 168 |
function addSwapInSwapOut(uint8 poolIdx, bool zeroForOne, int256 amount) public {
|
||
| 169 |
√ 2
|
⟳ 2
|
if(amount < 0) {
|
| 170 |
√ 2
|
⟳ 2
|
amount = amount * -1; |
| 171 |
} |
||
| 172 |
// exact amount out |
||
| 173 |
√ 4
|
⟳ 4
|
addSwap(poolIdx, -amount, zeroForOne); |
| 174 |
// exact amount in |
||
| 175 |
√ 4
|
addSwap(poolIdx, amount, !zeroForOne); |
|
| 176 | |||
| 177 |
√ 1
|
addShortcutSettle(); |
|
| 178 |
} |
||
| 179 | |||
| 180 |
/// @notice Creates a pool of highly concentrated liquidity. |
||
| 181 |
function addTargetedPool(uint8 currency1I, uint8 currency2I, uint24 fee, int128 liqDelta) public {
|
||
| 182 |
√ 2
|
⟳ 2
|
if (liqDelta < 0){
|
| 183 |
√ 1
|
⟳ 1
|
liqDelta = -liqDelta; |
| 184 |
} |
||
| 185 |
// concentrate the liquidity on 0,1 |
||
| 186 |
√ 5
|
⟳ 5
|
try this.addInitializeAndAddLiquidityAndSettle(currency1I, currency2I, 1, 79228162514264337593543950336, fee, 0, 1, liqDelta, 0) {}
|
| 187 |
catch (bytes memory err) {
|
||
| 188 |
√ 2
|
⟳ 2
|
bytes4 selector = bytes4(err); |
| 189 |
√ 5
|
⟳ 5
|
if (selector == Position.CannotUpdateEmptyPosition.selector) {
|
| 190 |
⟳ 3
|
assert(false); |
|
| 191 |
} |
||
| 192 |
} |
||
| 193 |
} |
||
| 194 | |||
| 195 |
/// @notice Creates a pool of highly concentrated liquidity with feeGrowthGlobal values that are close to overflowing |
||
| 196 |
function addTargetedPoolReadyToOverflow(uint8 currency1I, uint8 currency2I, uint24 fee) public {
|
||
| 197 |
√ 5
|
⟳ 5
|
addTargetedPool(currency1I, currency2I, fee, 1); |
| 198 |
√ 1
|
⟳ 1
|
runActionsWithShortcutSettle(); |
| 199 |
√ 5
|
⟳ 5
|
uint8 poolIdx = uint8(DeployedPools.length-1); |
| 200 | |||
| 201 |
√ 3
|
⟳ 3
|
addDonate(poolIdx, uint128(type(int128).max), uint128(type(int128).max)); |
| 202 |
√ 1
|
⟳ 1
|
runActionsWithShortcutSettle(); |
| 203 | |||
| 204 |
√ 4
|
addDonate(poolIdx, uint128(type(int128).max), uint128(type(int128).max)); |
|
| 205 |
√ 1
|
runActionsWithShortcutSettle(); |
|
| 206 |
} |
||
| 207 | |||
| 208 |
/// @notice Performs a donation, then settles and runs the action sequence. |
||
| 209 |
function addDonateAndSettle(uint256 amount0, uint256 amount1) public {
|
||
| 210 |
√ 5
|
⟳ 5
|
uint8 poolIdx = uint8(DeployedPools.length-1); |
| 211 |
√ 4
|
⟳ 4
|
addDonate(poolIdx, amount0, amount1); |
| 212 |
√ 1
|
⟳ 1
|
runActionsWithShortcutSettle(); |
| 213 |
} |
||
| 214 | |||
| 215 |
/// @notice This custom action is used to automatically settle all of the actor's outstanding deltas. |
||
| 216 |
function addShortcutSettle() public {
|
||
| 217 |
√ 36
|
⟳ 27
|
address actor = address(actionsRouter); |
| 218 | |||
| 219 |
√ 100
|
⟳ 75
|
bytes memory shortcutSettleCBParam = abi.encode(address(this), abi.encode(ActionCallbacks.SHORTCUT_SETTLE, abi.encode(actor))); |
| 220 |
√ 16
|
⟳ 12
|
actions.push(Actions.HARNESS_CALLBACK); |
| 221 |
params.push(shortcutSettleCBParam); |
||
| 222 | |||
| 223 |
} |
||
| 224 | |||
| 225 |
/// @notice Settles the actor's outstanding deltas and runs the actions sequence. |
||
| 226 |
function runActionsWithShortcutSettle() public {
|
||
| 227 |
√ 4
|
⟳ 3
|
addShortcutSettle(); |
| 228 |
√ 4
|
⟳ 3
|
runActions(); |
| 229 |
} |
||
| 230 | |||
| 231 |
/// @notice Performs a swap, settles the actor's balances, and runs the actions. |
||
| 232 |
function addSwapAndRunActions(uint8 poolIdx, int256 amountSpecified, bool zeroForOne) public {
|
||
| 233 |
√ 4
|
⟳ 4
|
addSwap(poolIdx, amountSpecified, zeroForOne); |
| 234 |
√ 1
|
⟳ 1
|
addShortcutSettle(); |
| 235 |
√ 1
|
⟳ 1
|
runActions(); |
| 236 |
} |
||
| 237 | |||
| 238 |
/// @notice Performs a burn, settles the actor's balances, and runs the actions. |
||
| 239 |
function addBurnAndRunActions(address from, uint8 curIdx, uint256 amount) public {
|
||
| 240 |
√ 4
|
⟳ 4
|
addBurn(from, curIdx, amount); |
| 241 |
addShortcutSettle(); |
||
| 242 |
runActions(); |
||
| 243 |
} |
||
| 244 | |||
| 245 |
/// @notice Performs a liquidity modification, settles the actor's balances, and runs the actions. |
||
| 246 |
function addModifyPositionAndRunActions(uint8 poolIdx, int24 lowTick, int24 highTick, int128 liqDelta, uint256 salt) public {
|
||
| 247 |
√ 6
|
⟳ 6
|
addModifyPosition(poolIdx, lowTick, highTick, liqDelta, salt); |
| 248 |
√ 1
|
⟳ 1
|
addShortcutSettle(); |
| 249 |
√ 1
|
⟳ 1
|
runActions(); |
| 250 |
} |
||
| 251 | |||
| 252 |
|
||
| 253 |
function _shortcutSettle(address actor) internal {
|
||
| 254 |
√ 20
|
⟳ 17
|
for( uint i=0; i<Currencies.length; i++) {
|
| 255 |
√ 18
|
⟳ 18
|
Currency c = Currencies[i]; |
| 256 |
√ 24
|
⟳ 24
|
int256 delta = manager.currencyDelta(actor, c); |
| 257 | |||
| 258 |
√ 12
|
⟳ 12
|
if(delta < 0) {
|
| 259 |
√ 7
|
⟳ 14
|
manager.sync(c); |
| 260 |
|
||
| 261 |
// manually reset remittances |
||
| 262 |
if(!(c == CurrencyLibrary.NATIVE)){
|
||
| 263 |
√ 1
|
⟳ 1
|
RemittanceCurrency = c; |
| 264 |
√ 1
|
⟳ 1
|
RemittanceAmount = 0; |
| 265 |
} |
||
| 266 | |||
| 267 |
√ 2
|
⟳ 4
|
uint256 amountOwed = uint256(-delta); |
| 268 |
if( c == CurrencyLibrary.NATIVE) {
|
||
| 269 |
√ 13
|
⟳ 13
|
emit LogUint256("sending native tokens to manager:", amountOwed);
|
| 270 |
√ 9
|
⟳ 9
|
manager.settleFor{value: amountOwed}(actor);
|
| 271 |
} else {
|
||
| 272 |
√ 13
|
⟳ 13
|
emit LogUint256("sending tokens to manager:", amountOwed);
|
| 273 |
√ 10
|
⟳ 10
|
c.transfer( address(manager), amountOwed); |
| 274 |
√ 7
|
⟳ 7
|
manager.settleFor(actor); |
| 275 |
} |
||
| 276 |
√ 13
|
⟳ 13
|
emit LogString("resetting remittance settleForshortcut");
|
| 277 |
√ 1
|
⟳ 1
|
RemittanceCurrency = CurrencyLibrary.NATIVE; |
| 278 |
√ 1
|
⟳ 1
|
RemittanceAmount = 0; |
| 279 |
|
||
| 280 | |||
| 281 |
√ 4
|
⟳ 4
|
_addToActorsCredits(actor, c, amountOwed); |
| 282 |
√ 10
|
⟳ 8
|
} else if (delta > 0) {
|
| 283 |
√ 13
|
⟳ 13
|
emit LogUint256("take tokens:", uint256(delta));
|
| 284 |
√ 4
|
⟳ 4
|
vm.prank(actor); |
| 285 |
√ 7
|
⟳ 7
|
manager.take(c, address(actor), uint256(delta)); |
| 286 |
√ 4
|
⟳ 4
|
_addToActorsDebts(actor, c, uint256(delta)); |
| 287 |
} |
||
| 288 |
} |
||
| 289 |
} |
||
| 290 |
} |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
interface IActionsHarness {
|
||
| 5 |
function routerCallback(bytes memory, bytes memory) external; |
||
| 6 |
} |
| Lines covered: | 0 / 225 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
abstract contract PropertiesAsserts {
|
||
| 5 |
event LogUint256(string, uint256); |
||
| 6 |
event LogInt256(string, int256); |
||
| 7 |
event LogAddress(string, address); |
||
| 8 |
event LogString(string); |
||
| 9 |
event LogBytes(string, bytes); |
||
| 10 | |||
| 11 |
event AssertFail(string); |
||
| 12 |
event AssertEqFail(string); |
||
| 13 |
event AssertNeqFail(string); |
||
| 14 |
event AssertGteFail(string); |
||
| 15 |
event AssertGtFail(string); |
||
| 16 |
event AssertLteFail(string); |
||
| 17 |
event AssertLtFail(string); |
||
| 18 | |||
| 19 |
event AssertPassed(string,uint256); |
||
| 20 | |||
| 21 |
string logPrefix; |
||
| 22 | |||
| 23 |
function assertWithMsg(bool b, string memory reason) internal {
|
||
| 24 |
if (!b) {
|
||
| 25 |
emit AssertFail(reason); |
||
| 26 |
assert(false); |
||
| 27 |
} |
||
| 28 |
} |
||
| 29 | |||
| 30 |
/// @notice asserts that a is equal to b. Violations are logged using reason. |
||
| 31 |
function assertEq(uint256 a, uint256 b, string memory reason) internal {
|
||
| 32 |
if (a != b) {
|
||
| 33 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 34 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 35 |
bytes memory assertMsg = abi.encodePacked( |
||
| 36 |
"Invalid: ", |
||
| 37 |
aStr, |
||
| 38 |
"!=", |
||
| 39 |
bStr, |
||
| 40 |
", reason: ", |
||
| 41 |
reason |
||
| 42 |
); |
||
| 43 |
emit AssertEqFail(string(assertMsg)); |
||
| 44 |
assert(false); |
||
| 45 |
} |
||
| 46 |
} |
||
| 47 | |||
| 48 |
/// @notice int256 version of assertEq |
||
| 49 |
function assertEq(int256 a, int256 b, string memory reason) internal {
|
||
| 50 |
if (a != b) {
|
||
| 51 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 52 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 53 |
bytes memory assertMsg = abi.encodePacked( |
||
| 54 |
"Invalid: ", |
||
| 55 |
aStr, |
||
| 56 |
"!=", |
||
| 57 |
bStr, |
||
| 58 |
", reason: ", |
||
| 59 |
reason |
||
| 60 |
); |
||
| 61 |
emit AssertEqFail(string(assertMsg)); |
||
| 62 |
assert(false); |
||
| 63 |
} |
||
| 64 |
} |
||
| 65 | |||
| 66 |
/// @notice asserts that a is not equal to b. Violations are logged using reason. |
||
| 67 |
function assertNeq(uint256 a, uint256 b, string memory reason) internal {
|
||
| 68 |
if (a == b) {
|
||
| 69 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 70 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 71 |
bytes memory assertMsg = abi.encodePacked( |
||
| 72 |
"Invalid: ", |
||
| 73 |
aStr, |
||
| 74 |
"==", |
||
| 75 |
bStr, |
||
| 76 |
", reason: ", |
||
| 77 |
reason |
||
| 78 |
); |
||
| 79 |
emit AssertNeqFail(string(assertMsg)); |
||
| 80 |
assert(false); |
||
| 81 |
} |
||
| 82 |
} |
||
| 83 | |||
| 84 |
/// @notice int256 version of assertNeq |
||
| 85 |
function assertNeq(int256 a, int256 b, string memory reason) internal {
|
||
| 86 |
if (a == b) {
|
||
| 87 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 88 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 89 |
bytes memory assertMsg = abi.encodePacked( |
||
| 90 |
"Invalid: ", |
||
| 91 |
aStr, |
||
| 92 |
"==", |
||
| 93 |
bStr, |
||
| 94 |
", reason: ", |
||
| 95 |
reason |
||
| 96 |
); |
||
| 97 |
emit AssertNeqFail(string(assertMsg)); |
||
| 98 |
assert(false); |
||
| 99 |
} |
||
| 100 |
} |
||
| 101 | |||
| 102 |
/// @notice asserts that a is greater than or equal to b. Violations are logged using reason. |
||
| 103 |
function assertGte(uint256 a, uint256 b, string memory reason) internal {
|
||
| 104 |
if (!(a >= b)) {
|
||
| 105 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 106 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 107 |
bytes memory assertMsg = abi.encodePacked( |
||
| 108 |
"Invalid: ", |
||
| 109 |
aStr, |
||
| 110 |
"<", |
||
| 111 |
bStr, |
||
| 112 |
" failed, reason: ", |
||
| 113 |
reason |
||
| 114 |
); |
||
| 115 |
emit AssertGteFail(string(assertMsg)); |
||
| 116 |
assert(false); |
||
| 117 |
} else {
|
||
| 118 |
uint256 distance = calcDistance(a,b); |
||
| 119 |
emit AssertPassed(reason, distance); |
||
| 120 |
} |
||
| 121 |
} |
||
| 122 | |||
| 123 |
/// @notice int256 version of assertGte |
||
| 124 |
function assertGte(int256 a, int256 b, string memory reason) internal {
|
||
| 125 |
if (!(a >= b)) {
|
||
| 126 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 127 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 128 |
bytes memory assertMsg = abi.encodePacked( |
||
| 129 |
"Invalid: ", |
||
| 130 |
aStr, |
||
| 131 |
"<", |
||
| 132 |
bStr, |
||
| 133 |
" failed, reason: ", |
||
| 134 |
reason |
||
| 135 |
); |
||
| 136 |
emit AssertGteFail(string(assertMsg)); |
||
| 137 |
assert(false); |
||
| 138 |
} else {
|
||
| 139 |
uint256 distance = calcDistance(a,b); |
||
| 140 |
emit AssertPassed(reason, distance); |
||
| 141 |
} |
||
| 142 |
} |
||
| 143 | |||
| 144 | |||
| 145 | |||
| 146 |
/// @notice asserts that a is greater than b. Violations are logged using reason. |
||
| 147 |
function assertGt(uint256 a, uint256 b, string memory reason) internal {
|
||
| 148 |
if (!(a > b)) {
|
||
| 149 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 150 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 151 |
bytes memory assertMsg = abi.encodePacked( |
||
| 152 |
"Invalid: ", |
||
| 153 |
aStr, |
||
| 154 |
"<=", |
||
| 155 |
bStr, |
||
| 156 |
" failed, reason: ", |
||
| 157 |
reason |
||
| 158 |
); |
||
| 159 |
emit AssertGtFail(string(assertMsg)); |
||
| 160 |
assert(false); |
||
| 161 |
} else {
|
||
| 162 |
uint256 distance = calcDistance(a,b); |
||
| 163 |
emit AssertPassed(reason, distance-1); |
||
| 164 |
} |
||
| 165 |
} |
||
| 166 | |||
| 167 |
/// @notice int256 version of assertGt |
||
| 168 |
function assertGt(int256 a, int256 b, string memory reason) internal {
|
||
| 169 |
if (!(a > b)) {
|
||
| 170 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 171 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 172 |
bytes memory assertMsg = abi.encodePacked( |
||
| 173 |
"Invalid: ", |
||
| 174 |
aStr, |
||
| 175 |
"<=", |
||
| 176 |
bStr, |
||
| 177 |
" failed, reason: ", |
||
| 178 |
reason |
||
| 179 |
); |
||
| 180 |
emit AssertGtFail(string(assertMsg)); |
||
| 181 |
assert(false); |
||
| 182 |
} else {
|
||
| 183 |
uint256 distance = calcDistance(a,b); |
||
| 184 |
emit AssertPassed(reason, distance-1); |
||
| 185 |
} |
||
| 186 |
} |
||
| 187 | |||
| 188 |
/// @notice asserts that a is less than or equal to b. Violations are logged using reason. |
||
| 189 |
function assertLte(uint256 a, uint256 b, string memory reason) internal {
|
||
| 190 |
if (!(a <= b)) {
|
||
| 191 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 192 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 193 |
bytes memory assertMsg = abi.encodePacked( |
||
| 194 |
"Invalid: ", |
||
| 195 |
aStr, |
||
| 196 |
">", |
||
| 197 |
bStr, |
||
| 198 |
" failed, reason: ", |
||
| 199 |
reason |
||
| 200 |
); |
||
| 201 |
emit AssertLteFail(string(assertMsg)); |
||
| 202 |
assert(false); |
||
| 203 |
} else {
|
||
| 204 |
uint256 distance = calcDistance(a,b); |
||
| 205 |
emit AssertPassed(reason, distance); |
||
| 206 |
} |
||
| 207 |
} |
||
| 208 | |||
| 209 |
/// @notice int256 version of assertLte |
||
| 210 |
function assertLte(int256 a, int256 b, string memory reason) internal {
|
||
| 211 |
if (!(a <= b)) {
|
||
| 212 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 213 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 214 |
bytes memory assertMsg = abi.encodePacked( |
||
| 215 |
"Invalid: ", |
||
| 216 |
aStr, |
||
| 217 |
">", |
||
| 218 |
bStr, |
||
| 219 |
" failed, reason: ", |
||
| 220 |
reason |
||
| 221 |
); |
||
| 222 |
emit AssertLteFail(string(assertMsg)); |
||
| 223 |
assert(false); |
||
| 224 |
} else {
|
||
| 225 |
uint256 distance = calcDistance(a,b); |
||
| 226 |
emit AssertPassed(reason, distance); |
||
| 227 |
} |
||
| 228 |
} |
||
| 229 | |||
| 230 |
/// @notice asserts that a is less than b. Violations are logged using reason. |
||
| 231 |
function assertLt(uint256 a, uint256 b, string memory reason) internal {
|
||
| 232 |
if (!(a < b)) {
|
||
| 233 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 234 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 235 |
bytes memory assertMsg = abi.encodePacked( |
||
| 236 |
"Invalid: ", |
||
| 237 |
aStr, |
||
| 238 |
">=", |
||
| 239 |
bStr, |
||
| 240 |
" failed, reason: ", |
||
| 241 |
reason |
||
| 242 |
); |
||
| 243 |
emit AssertLtFail(string(assertMsg)); |
||
| 244 |
assert(false); |
||
| 245 |
} else {
|
||
| 246 |
uint256 distance = calcDistance(a,b); |
||
| 247 |
emit AssertPassed(reason, distance-1); |
||
| 248 |
} |
||
| 249 |
} |
||
| 250 | |||
| 251 |
/// @notice int256 version of assertLt |
||
| 252 |
function assertLt(int256 a, int256 b, string memory reason) internal {
|
||
| 253 |
if (!(a < b)) {
|
||
| 254 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 255 |
string memory bStr = PropertiesLibString.toString(b); |
||
| 256 |
bytes memory assertMsg = abi.encodePacked( |
||
| 257 |
"Invalid: ", |
||
| 258 |
aStr, |
||
| 259 |
">=", |
||
| 260 |
bStr, |
||
| 261 |
" failed, reason: ", |
||
| 262 |
reason |
||
| 263 |
); |
||
| 264 |
emit AssertLtFail(string(assertMsg)); |
||
| 265 |
assert(false); |
||
| 266 |
} else {
|
||
| 267 |
uint256 distance = calcDistance(a,b); |
||
| 268 |
emit AssertPassed(reason, distance); |
||
| 269 |
} |
||
| 270 |
} |
||
| 271 | |||
| 272 |
/// @notice Clamps value to be between low and high, both inclusive |
||
| 273 |
function clampBetween( |
||
| 274 |
uint256 value, |
||
| 275 |
uint256 low, |
||
| 276 |
uint256 high |
||
| 277 |
) internal returns (uint256) {
|
||
| 278 |
if (value < low || value > high) {
|
||
| 279 |
uint ans = low + (value % (high - low + 1)); |
||
| 280 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 281 |
string memory ansStr = PropertiesLibString.toString(ans); |
||
| 282 |
bytes memory message = abi.encodePacked( |
||
| 283 |
"Clamping value ", |
||
| 284 |
valueStr, |
||
| 285 |
" to ", |
||
| 286 |
ansStr |
||
| 287 |
); |
||
| 288 |
emit LogString(string(message)); |
||
| 289 |
return ans; |
||
| 290 |
} |
||
| 291 |
return value; |
||
| 292 |
} |
||
| 293 | |||
| 294 |
/// @notice int256 version of clampBetween |
||
| 295 |
function clampBetween( |
||
| 296 |
int256 value, |
||
| 297 |
int256 low, |
||
| 298 |
int256 high |
||
| 299 |
) internal returns (int256) {
|
||
| 300 |
if (value < low || value > high) {
|
||
| 301 |
int range = high - low + 1; |
||
| 302 |
int clamped = (value - low) % (range); |
||
| 303 |
if (clamped < 0) clamped += range; |
||
| 304 |
int ans = low + clamped; |
||
| 305 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 306 |
string memory ansStr = PropertiesLibString.toString(ans); |
||
| 307 |
bytes memory message = abi.encodePacked( |
||
| 308 |
"Clamping value ", |
||
| 309 |
valueStr, |
||
| 310 |
" to ", |
||
| 311 |
ansStr |
||
| 312 |
); |
||
| 313 |
emit LogString(string(message)); |
||
| 314 |
return ans; |
||
| 315 |
} |
||
| 316 |
return value; |
||
| 317 |
} |
||
| 318 | |||
| 319 |
/// @notice clamps a to be less than b |
||
| 320 |
function clampLt(uint256 a, uint256 b) internal returns (uint256) {
|
||
| 321 |
if (!(a < b)) {
|
||
| 322 |
assertNeq( |
||
| 323 |
b, |
||
| 324 |
0, |
||
| 325 |
"clampLt cannot clamp value a to be less than zero. Check your inputs/assumptions." |
||
| 326 |
); |
||
| 327 |
uint256 value = a % b; |
||
| 328 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 329 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 330 |
bytes memory message = abi.encodePacked( |
||
| 331 |
"Clamping value ", |
||
| 332 |
aStr, |
||
| 333 |
" to ", |
||
| 334 |
valueStr |
||
| 335 |
); |
||
| 336 |
emit LogString(string(message)); |
||
| 337 |
return value; |
||
| 338 |
} |
||
| 339 |
return a; |
||
| 340 |
} |
||
| 341 | |||
| 342 |
/// @notice int256 version of clampLt |
||
| 343 |
function clampLt(int256 a, int256 b) internal returns (int256) {
|
||
| 344 |
if (!(a < b)) {
|
||
| 345 |
int256 value = b - 1; |
||
| 346 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 347 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 348 |
bytes memory message = abi.encodePacked( |
||
| 349 |
"Clamping value ", |
||
| 350 |
aStr, |
||
| 351 |
" to ", |
||
| 352 |
valueStr |
||
| 353 |
); |
||
| 354 |
emit LogString(string(message)); |
||
| 355 |
return value; |
||
| 356 |
} |
||
| 357 |
return a; |
||
| 358 |
} |
||
| 359 | |||
| 360 |
/// @notice clamps a to be less than or equal to b |
||
| 361 |
function clampLte(uint256 a, uint256 b) internal returns (uint256) {
|
||
| 362 |
if (!(a <= b)) {
|
||
| 363 |
uint256 value = a % (b + 1); |
||
| 364 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 365 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 366 |
bytes memory message = abi.encodePacked( |
||
| 367 |
"Clamping value ", |
||
| 368 |
aStr, |
||
| 369 |
" to ", |
||
| 370 |
valueStr |
||
| 371 |
); |
||
| 372 |
emit LogString(string(message)); |
||
| 373 |
return value; |
||
| 374 |
} |
||
| 375 |
return a; |
||
| 376 |
} |
||
| 377 | |||
| 378 |
/// @notice int256 version of clampLte |
||
| 379 |
function clampLte(int256 a, int256 b) internal returns (int256) {
|
||
| 380 |
if (!(a <= b)) {
|
||
| 381 |
int256 value = b; |
||
| 382 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 383 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 384 |
bytes memory message = abi.encodePacked( |
||
| 385 |
"Clamping value ", |
||
| 386 |
aStr, |
||
| 387 |
" to ", |
||
| 388 |
valueStr |
||
| 389 |
); |
||
| 390 |
emit LogString(string(message)); |
||
| 391 |
return value; |
||
| 392 |
} |
||
| 393 |
return a; |
||
| 394 |
} |
||
| 395 | |||
| 396 |
/// @notice clamps a to be greater than b |
||
| 397 |
function clampGt(uint256 a, uint256 b) internal returns (uint256) {
|
||
| 398 |
if (!(a > b)) {
|
||
| 399 |
assertNeq( |
||
| 400 |
b, |
||
| 401 |
type(uint256).max, |
||
| 402 |
"clampGt cannot clamp value a to be larger than uint256.max. Check your inputs/assumptions." |
||
| 403 |
); |
||
| 404 |
uint256 value = b + 1; |
||
| 405 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 406 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 407 |
bytes memory message = abi.encodePacked( |
||
| 408 |
"Clamping value ", |
||
| 409 |
aStr, |
||
| 410 |
" to ", |
||
| 411 |
valueStr |
||
| 412 |
); |
||
| 413 |
emit LogString(string(message)); |
||
| 414 |
return value; |
||
| 415 |
} else {
|
||
| 416 |
return a; |
||
| 417 |
} |
||
| 418 |
} |
||
| 419 | |||
| 420 |
/// @notice int256 version of clampGt |
||
| 421 |
function clampGt(int256 a, int256 b) internal returns (int256) {
|
||
| 422 |
if (!(a > b)) {
|
||
| 423 |
int256 value = b + 1; |
||
| 424 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 425 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 426 |
bytes memory message = abi.encodePacked( |
||
| 427 |
"Clamping value ", |
||
| 428 |
aStr, |
||
| 429 |
" to ", |
||
| 430 |
valueStr |
||
| 431 |
); |
||
| 432 |
emit LogString(string(message)); |
||
| 433 |
return value; |
||
| 434 |
} else {
|
||
| 435 |
return a; |
||
| 436 |
} |
||
| 437 |
} |
||
| 438 | |||
| 439 |
/// @notice clamps a to be greater than or equal to b |
||
| 440 |
function clampGte(uint256 a, uint256 b) internal returns (uint256) {
|
||
| 441 |
if (!(a > b)) {
|
||
| 442 |
uint256 value = b; |
||
| 443 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 444 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 445 |
bytes memory message = abi.encodePacked( |
||
| 446 |
"Clamping value ", |
||
| 447 |
aStr, |
||
| 448 |
" to ", |
||
| 449 |
valueStr |
||
| 450 |
); |
||
| 451 |
emit LogString(string(message)); |
||
| 452 |
return value; |
||
| 453 |
} |
||
| 454 |
return a; |
||
| 455 |
} |
||
| 456 | |||
| 457 |
/// @notice int256 version of clampGte |
||
| 458 |
function clampGte(int256 a, int256 b) internal returns (int256) {
|
||
| 459 |
if (!(a > b)) {
|
||
| 460 |
int256 value = b; |
||
| 461 |
string memory aStr = PropertiesLibString.toString(a); |
||
| 462 |
string memory valueStr = PropertiesLibString.toString(value); |
||
| 463 |
bytes memory message = abi.encodePacked( |
||
| 464 |
"Clamping value ", |
||
| 465 |
aStr, |
||
| 466 |
" to ", |
||
| 467 |
valueStr |
||
| 468 |
); |
||
| 469 |
emit LogString(string(message)); |
||
| 470 |
return value; |
||
| 471 |
} |
||
| 472 |
return a; |
||
| 473 |
} |
||
| 474 | |||
| 475 |
/// @notice returns "true" if adding the two unsigned ints would result in an overflow |
||
| 476 |
function doesSumOverflow(uint256 a, uint256 b) internal returns (bool) {
|
||
| 477 |
unchecked {
|
||
| 478 |
if( a + b < a ){
|
||
| 479 |
return true; |
||
| 480 |
} else {
|
||
| 481 |
return false; |
||
| 482 |
} |
||
| 483 |
} |
||
| 484 |
} |
||
| 485 | |||
| 486 |
/// @notice returns "true" if adding the two signed ints would result in an overflow |
||
| 487 |
function doesSumOverflow(int256 a, int256 b) internal returns (bool) {
|
||
| 488 |
if (a < 0 || b < 0) {
|
||
| 489 |
return false; |
||
| 490 |
} else {
|
||
| 491 |
return doesSumOverflow(uint256(a), uint256(b)); |
||
| 492 |
} |
||
| 493 |
} |
||
| 494 | |||
| 495 |
/// @notice returns "true" if adding the two signed ints would result in an underflow |
||
| 496 |
function doesSumUnderflow(int256 a, int256 b) internal returns (bool) {
|
||
| 497 |
if (a > 0 || b > 0) {
|
||
| 498 |
return false; |
||
| 499 |
} else {
|
||
| 500 |
unchecked {
|
||
| 501 |
int256 sum = a + b; |
||
| 502 |
if (sum > a) {
|
||
| 503 |
return true; |
||
| 504 |
} else {
|
||
| 505 |
return false; |
||
| 506 |
} |
||
| 507 |
} |
||
| 508 |
} |
||
| 509 |
} |
||
| 510 | |||
| 511 |
/// @notice returns "true" if adding the two signed ints would result in an overflow or underflow |
||
| 512 |
function doesSumOverUnderflow(int256 a, int256 b) internal returns (bool) {
|
||
| 513 |
return doesSumOverflow(a,b) || doesSumUnderflow(a,b); |
||
| 514 |
} |
||
| 515 | |||
| 516 |
/// @notice Calculates the numeric distance between two integers. |
||
| 517 |
function calcDistance(int256 a, int256 b) internal returns (uint256) {
|
||
| 518 |
if (b > a) {
|
||
| 519 |
int256 tmp = a; |
||
| 520 |
a = b; |
||
| 521 |
b = tmp; |
||
| 522 |
} |
||
| 523 |
uint256 trueDistance; |
||
| 524 |
unchecked {
|
||
| 525 |
int256 distance = a - b; |
||
| 526 |
if(distance >= 0) {
|
||
| 527 |
trueDistance = uint256(distance); |
||
| 528 |
} else {
|
||
| 529 |
a -= type(int256).max; |
||
| 530 |
trueDistance = uint256(a - b) + uint256(type(int256).max); |
||
| 531 |
} |
||
| 532 |
} |
||
| 533 |
return trueDistance; |
||
| 534 |
} |
||
| 535 | |||
| 536 |
/// @notice Calculates the numeric distance between two unsigned integers. |
||
| 537 |
function calcDistance(uint256 a, uint256 b) internal returns (uint256) {
|
||
| 538 |
if (b > a) {
|
||
| 539 |
uint256 tmp = a; |
||
| 540 |
a = b; |
||
| 541 |
b = tmp; |
||
| 542 |
} |
||
| 543 |
return a - b; |
||
| 544 |
} |
||
| 545 |
} |
||
| 546 | |||
| 547 |
/// @notice Efficient library for creating string representations of integers. |
||
| 548 |
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) |
||
| 549 |
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol) |
||
| 550 |
/// @dev Name of the library is modified to prevent collisions with contract-under-test uses of LibString |
||
| 551 |
library PropertiesLibString {
|
||
| 552 |
function toString(int256 value) internal pure returns (string memory str) {
|
||
| 553 |
uint256 absValue = value >= 0 ? uint256(value) : uint256(-value); |
||
| 554 |
str = toString(absValue); |
||
| 555 | |||
| 556 |
if (value < 0) {
|
||
| 557 |
str = string(abi.encodePacked("-", str));
|
||
| 558 |
} |
||
| 559 |
} |
||
| 560 | |||
| 561 |
function toString(uint256 value) internal pure returns (string memory str) {
|
||
| 562 |
/// @solidity memory-safe-assembly |
||
| 563 |
assembly {
|
||
| 564 |
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes |
||
| 565 |
// to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the |
||
| 566 |
// trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes. |
||
| 567 |
let newFreeMemoryPointer := add(mload(0x40), 160) |
||
| 568 | |||
| 569 |
// Update the free memory pointer to avoid overriding our string. |
||
| 570 |
mstore(0x40, newFreeMemoryPointer) |
||
| 571 | |||
| 572 |
// Assign str to the end of the zone of newly allocated memory. |
||
| 573 |
str := sub(newFreeMemoryPointer, 32) |
||
| 574 | |||
| 575 |
// Clean the last word of memory it may not be overwritten. |
||
| 576 |
mstore(str, 0) |
||
| 577 | |||
| 578 |
// Cache the end of the memory to calculate the length later. |
||
| 579 |
let end := str |
||
| 580 | |||
| 581 |
// We write the string from rightmost digit to leftmost digit. |
||
| 582 |
// The following is essentially a do-while loop that also handles the zero case. |
||
| 583 |
// prettier-ignore |
||
| 584 |
for { let temp := value } 1 {} {
|
||
| 585 |
// Move the pointer 1 byte to the left. |
||
| 586 |
str := sub(str, 1) |
||
| 587 | |||
| 588 |
// Write the character to the pointer. |
||
| 589 |
// The ASCII index of the '0' character is 48. |
||
| 590 |
mstore8(str, add(48, mod(temp, 10))) |
||
| 591 | |||
| 592 |
// Keep dividing temp until zero. |
||
| 593 |
temp := div(temp, 10) |
||
| 594 | |||
| 595 |
// prettier-ignore |
||
| 596 |
if iszero(temp) { break }
|
||
| 597 |
} |
||
| 598 | |||
| 599 |
// Compute and cache the final total length of the string. |
||
| 600 |
let length := sub(end, str) |
||
| 601 | |||
| 602 |
// Move the pointer 32 bytes leftwards to make room for the length. |
||
| 603 |
str := sub(str, 32) |
||
| 604 | |||
| 605 |
// Store the string's length at the start of memory allocated for our string. |
||
| 606 |
mstore(str, length) |
||
| 607 |
} |
||
| 608 |
} |
||
| 609 | |||
| 610 |
function toString(address value) internal pure returns (string memory str) {
|
||
| 611 |
bytes memory s = new bytes(40); |
||
| 612 |
for (uint i = 0; i < 20; i++) {
|
||
| 613 |
bytes1 b = bytes1( |
||
| 614 |
uint8(uint(uint160(value)) / (2 ** (8 * (19 - i)))) |
||
| 615 |
); |
||
| 616 |
bytes1 hi = bytes1(uint8(b) / 16); |
||
| 617 |
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); |
||
| 618 |
s[2 * i] = char(hi); |
||
| 619 |
s[2 * i + 1] = char(lo); |
||
| 620 |
} |
||
| 621 |
return string(s); |
||
| 622 |
} |
||
| 623 | |||
| 624 |
function char(bytes1 b) internal pure returns (bytes1 c) {
|
||
| 625 |
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); |
||
| 626 |
else return bytes1(uint8(b) + 0x57); |
||
| 627 |
} |
||
| 628 |
} |
| Lines covered: | 0 / 25 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 5 | |||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 8 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 9 | |||
| 10 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 11 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 12 | |||
| 13 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 14 | |||
| 15 |
import {PropertiesAsserts} from "test/trailofbits/PropertiesHelper.sol";
|
||
| 16 | |||
| 17 | |||
| 18 |
/// @notice This contract provides a way for the harness to perform "shadow accounting", a technique where |
||
| 19 |
/// the harness maintains its own copy of the system's balances, deltas, and remittances. Gas-optimized |
||
| 20 |
/// protocols like v4 often need to perform indirect accounting to save gas, but this opens the possibility |
||
| 21 |
/// of an error in that indirect accounting that can be exploited, such as an LPer for one pool being able to |
||
| 22 |
/// withdraw more tokens than should exist in that pool. |
||
| 23 |
/// By maintaining our own, direct copy of the accounting, we can compare it to the results of v4's indirect |
||
| 24 |
/// accounting to verify the indirect accounting's correctness. |
||
| 25 |
contract ShadowAccounting is PropertiesAsserts, Deployers {
|
||
| 26 |
using TransientStateLibrary for IPoolManager; |
||
| 27 | |||
| 28 |
struct PoolBalance {
|
||
| 29 |
// While it makes more sense for these to be uint256, it drastically increases the complexity of the casting/math. |
||
| 30 |
// Fix it in the future. |
||
| 31 |
int256 amount0; |
||
| 32 |
int256 amount1; |
||
| 33 |
} |
||
| 34 | |||
| 35 |
// Tracks the tokens available in each pool for trading. |
||
| 36 |
mapping(PoolId => PoolBalance) PoolLiquidities; |
||
| 37 | |||
| 38 |
// Tracks the currency deltas for each actor. |
||
| 39 |
mapping(address => mapping(Currency => int256)) CurrencyDeltas; |
||
| 40 | |||
| 41 |
// Tracks the liquidity available for swapping within the entire system. |
||
| 42 |
mapping(Currency => uint256) SingletonLiquidity; |
||
| 43 | |||
| 44 |
// Tracks the amount of LP fees available for LPers to withdraw for each currency |
||
| 45 |
mapping(Currency => uint256) SingletonLPFees; |
||
| 46 | |||
| 47 |
// Our own counter for outstanding deltas, based on CurrencyDeltas. |
||
| 48 |
int256 OutstandingDeltas; |
||
| 49 | |||
| 50 |
// Used to track remittances for settle() properties. |
||
| 51 |
Currency RemittanceCurrency = CurrencyLibrary.NATIVE; |
||
| 52 |
// Any code that transfers currency between the actor and the pool manager should update this. |
||
| 53 |
int256 RemittanceAmount; |
||
| 54 | |||
| 55 |
// This should only be called when we expect transient storage to be cleared, ex: after a transaction terminates. |
||
| 56 |
function _clearTransientRemittances() internal {
|
||
| 57 |
RemittanceCurrency = CurrencyLibrary.NATIVE; |
||
| 58 |
RemittanceAmount = 0; |
||
| 59 |
} |
||
| 60 | |||
| 61 |
function _addToActorsDebts(address actor, Currency currency, uint256 amount) internal {
|
||
| 62 |
// UNI-ACTION-4 |
||
| 63 |
assertLte(amount, uint256(type(int256).max), "Shadow Accounting: An actor's debited delta must not exceed int256.max for any single action."); |
||
| 64 |
_updateCurrencyDelta(actor, currency, -int256(amount)); |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function _addToActorsCredits(address actor, Currency currency, uint256 amount) internal {
|
||
| 68 |
// UNI-ACTION-5 |
||
| 69 |
assertLte(amount, uint256(type(int256).max), "Shadow Accounting: An actor's credited delta must not exceed int256.max for any single action."); |
||
| 70 |
_updateCurrencyDelta(actor, currency, int256(amount)); |
||
| 71 |
} |
||
| 72 |
|
||
| 73 |
function _updateCurrencyDelta(address actor, Currency currency, int256 delta) internal {
|
||
| 74 |
int256 prev = CurrencyDeltas[actor][currency]; |
||
| 75 |
int256 newD = prev + delta; |
||
| 76 | |||
| 77 |
CurrencyDeltas[actor][currency] = newD; |
||
| 78 |
emit LogAddress("Shadow Accounting: Updating delta for actor", actor);
|
||
| 79 |
emit LogAddress("Shadow Accounting: Updating currency being modified", address(Currency.unwrap(currency)));
|
||
| 80 | |||
| 81 |
if (prev == 0 && newD != 0) {
|
||
| 82 |
// add to array |
||
| 83 |
emit LogAddress("Shadow Accounting: Adding currency to actor's deltas: ", address(Currency.unwrap(currency)));
|
||
| 84 |
OutstandingDeltas += 1; |
||
| 85 |
} else if (prev != 0 && newD == 0) {
|
||
| 86 |
emit LogString("Shadow Accounting: Removing currency from actor's deltas");
|
||
| 87 |
OutstandingDeltas -= 1; |
||
| 88 |
} |
||
| 89 |
emit LogInt256("Shadow Accounting: New delta: ", newD);
|
||
| 90 |
emit LogInt256("Shadow Accounting: Prev delta: ", prev);
|
||
| 91 |
_sanityCheckCurrencyDelta(actor, currency); |
||
| 92 |
} |
||
| 93 | |||
| 94 |
function _sanityCheckCurrencyDelta(address actor, Currency currency) private {
|
||
| 95 |
int256 uniswapCurrencyDelta = manager.currencyDelta(actor, currency); |
||
| 96 |
int256 harnessCurrencyDelta = CurrencyDeltas[actor][currency]; |
||
| 97 |
assertEq(uniswapCurrencyDelta, harnessCurrencyDelta, "BUG: Harness currency delta does not match uniswap currency delta"); |
||
| 98 |
} |
||
| 99 | |||
| 100 | |||
| 101 |
} |
| Lines covered: | 0 / 116 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 5 | |||
| 6 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 | |||
| 9 |
import {LiquidityMath} from "src/libraries/LiquidityMath.sol";
|
||
| 10 |
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
|
||
| 11 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 12 |
import {Pool} from "src/libraries/Pool.sol";
|
||
| 13 |
import {SafeCast} from "src/libraries/SafeCast.sol";
|
||
| 14 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {TickBitmap} from "src/libraries/TickBitmap.sol";
|
||
| 17 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 18 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 19 | |||
| 20 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 21 | |||
| 22 |
import {PropertiesAsserts} from "test/trailofbits/PropertiesHelper.sol";
|
||
| 23 | |||
| 24 |
/// @notice This contract contains a limited reproduction of the v4 state machine. |
||
| 25 |
/// Context: Some information in the v4 architecture is not directly accessible from any kind of |
||
| 26 |
/// solidity-based getter (example: the amount of LP fees collected for a given swap). |
||
| 27 |
/// Since our harness is the only entrypoint for the system, we can cache every single liquidity |
||
| 28 |
/// position, then reconstruct the internal tickInfo and tickBitmap for each pool |
||
| 29 |
/// immediately before swapping. |
||
| 30 |
/// We can then "simulate" the swap against our reconstructed tickInfo/tickBitmap, extracting |
||
| 31 |
/// the values we need for verifying properties. |
||
| 32 |
/// In the future, this technique can be extended for modifyLiquidity and be used to verify |
||
| 33 |
/// reversion properties. |
||
| 34 |
contract V4StateMachine is PropertiesAsserts, Deployers {
|
||
| 35 |
using PoolIdLibrary for PoolKey; |
||
| 36 |
using ProtocolFeeLibrary for *; |
||
| 37 |
using TickBitmap for mapping(int16 => uint256); |
||
| 38 |
using TransientStateLibrary for IPoolManager; |
||
| 39 |
using SafeCast for *; |
||
| 40 |
using StateLibrary for IPoolManager; |
||
| 41 | |||
| 42 |
struct TickInfoUnpacked {
|
||
| 43 |
uint128 liquidityGross; |
||
| 44 |
int128 liquidityNet; |
||
| 45 |
} |
||
| 46 | |||
| 47 |
struct TickDescr{
|
||
| 48 |
int24 tick; |
||
| 49 |
int24 tickSpacing; |
||
| 50 |
} |
||
| 51 | |||
| 52 |
struct PositionInfo {
|
||
| 53 |
uint128 liquidity; |
||
| 54 |
int24 tickLower; |
||
| 55 |
int24 tickUpper; |
||
| 56 |
} |
||
| 57 | |||
| 58 |
// This is used for storing the tickBitmap for all pools. It is deleted and rebuilt before every simulation. |
||
| 59 |
mapping(int16 => uint256) private TickBitmapProxy; |
||
| 60 |
// Used for deleting the TickBitmapProxy mapping |
||
| 61 |
TickDescr[] TickBitmapIndexes; |
||
| 62 | |||
| 63 |
// Used for reconstructing the tickInfo for all pools. It is deleted and rebuilt before every simulation. |
||
| 64 |
mapping(int24 => TickInfoUnpacked) private TickInfos; |
||
| 65 |
mapping(int24 => bool) private TickInfoInitialized; |
||
| 66 |
// Used for deleting the TickInfos mapping |
||
| 67 |
int24[] private TickInfoIndexes; |
||
| 68 | |||
| 69 |
// a poolId lookup of all positions for the pool. |
||
| 70 |
// Includes positions that are cleared, they simply have 0 liquidity. |
||
| 71 |
// The LiquidityActionProps contract handles adding/updating liquidity positions. |
||
| 72 |
// In the future, consider moving the logic for updating positions into this class to improve decoupling. |
||
| 73 |
mapping(PoolId => PositionInfo[]) PoolPositions; |
||
| 74 | |||
| 75 |
// key is keccak(poolId, positionKey) |
||
| 76 |
// The LiquidityActionProps contract handles adding/updating liquidity positions. |
||
| 77 |
mapping(bytes32 => int) PositionInfoIndex; |
||
| 78 | |||
| 79 |
/// @notice This function is the main entrypoint for the simulated state machine. |
||
| 80 |
function _calculateExpectedLPAndProtocolFees(PoolKey memory pool, bool zeroForOne, int256 amount, uint256 priceLimit) internal returns (uint256, uint256) {
|
||
| 81 |
_updateTickBitmapProxy(pool); |
||
| 82 | |||
| 83 |
// Most of following code is a near 1:1 reproduction of Pool.swap() |
||
| 84 |
uint256 feeGrowthGlobalX128; |
||
| 85 |
{
|
||
| 86 |
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(pool.toId()); |
||
| 87 |
feeGrowthGlobalX128 = zeroForOne ? feeGrowthGlobal0X128 : feeGrowthGlobal1X128; |
||
| 88 |
} |
||
| 89 | |||
| 90 |
Pool.SwapState memory state; |
||
| 91 |
uint160 curPrice; |
||
| 92 |
uint24 swapFee; |
||
| 93 |
uint24 protocolFee; |
||
| 94 |
{
|
||
| 95 |
int24 curTick; |
||
| 96 |
uint24 protocolFeeRaw; |
||
| 97 |
uint24 lpFee; |
||
| 98 |
(curPrice, curTick, protocolFeeRaw, lpFee) = manager.getSlot0(pool.toId()); |
||
| 99 |
state.amountSpecifiedRemaining = amount; |
||
| 100 |
state.amountCalculated = 0; |
||
| 101 |
state.sqrtPriceX96 = curPrice; |
||
| 102 |
state.tick = curTick; |
||
| 103 |
state.feeGrowthGlobalX128 = feeGrowthGlobalX128; |
||
| 104 |
state.liquidity = manager.getLiquidity(pool.toId()); |
||
| 105 | |||
| 106 |
if(zeroForOne){
|
||
| 107 |
protocolFee = protocolFeeRaw.getZeroForOneFee(); |
||
| 108 |
} else {
|
||
| 109 |
protocolFee = protocolFeeRaw.getOneForZeroFee(); |
||
| 110 |
} |
||
| 111 | |||
| 112 |
if(protocolFee == 0) {
|
||
| 113 |
swapFee = lpFee; |
||
| 114 |
} else {
|
||
| 115 |
swapFee = uint16(protocolFee).calculateSwapFee(lpFee); |
||
| 116 |
} |
||
| 117 |
} |
||
| 118 | |||
| 119 |
{
|
||
| 120 |
bool exactInput = amount < 0; |
||
| 121 |
if((swapFee == LPFeeLibrary.MAX_LP_FEE && !exactInput) || amount == 0) {
|
||
| 122 |
return (0,0); |
||
| 123 |
} |
||
| 124 |
} |
||
| 125 | |||
| 126 |
if (zeroForOne) {
|
||
| 127 |
if (priceLimit >= curPrice) {
|
||
| 128 |
return (0,0); |
||
| 129 |
} |
||
| 130 |
if (priceLimit < TickMath.MIN_SQRT_PRICE) {
|
||
| 131 |
return (0,0); |
||
| 132 |
} |
||
| 133 |
} else {
|
||
| 134 |
if (priceLimit <= curPrice) {
|
||
| 135 |
return (0,0); |
||
| 136 |
} |
||
| 137 |
if (priceLimit >= TickMath.MAX_SQRT_PRICE) {
|
||
| 138 |
return (0,0); |
||
| 139 |
} |
||
| 140 |
} |
||
| 141 | |||
| 142 |
// pack into a swapinfo to save stack |
||
| 143 |
Pool.SwapParams memory swapInfo = Pool.SwapParams( |
||
| 144 |
pool.tickSpacing, |
||
| 145 |
zeroForOne, |
||
| 146 |
amount, |
||
| 147 |
uint160(priceLimit), |
||
| 148 |
0 |
||
| 149 |
); |
||
| 150 |
return _calculateSteps(swapInfo, state, swapFee, pool.tickSpacing, protocolFee); |
||
| 151 |
} |
||
| 152 | |||
| 153 | |||
| 154 |
/// @notice Continuation of _calculateExpectedLPAndProtocolFees. Needed to save stack space. |
||
| 155 |
function _calculateSteps( Pool.SwapParams memory params, Pool.SwapState memory state, uint24 swapFee, int24 tickSpacing, uint24 protocolFee) private view returns (uint256, uint256) {
|
||
| 156 |
Pool.StepComputations memory step; |
||
| 157 |
bool exactInput = params.amountSpecified < 0; |
||
| 158 |
uint256 feeForProtocol; |
||
| 159 |
uint256 feeForLp; |
||
| 160 |
while (!(state.amountSpecifiedRemaining == 0 || state.sqrtPriceX96 == params.sqrtPriceLimitX96)) {
|
||
| 161 |
step.sqrtPriceStartX96 = state.sqrtPriceX96; |
||
| 162 | |||
| 163 |
(step.tickNext, step.initialized) = |
||
| 164 |
TickBitmapProxy.nextInitializedTickWithinOneWord(state.tick, tickSpacing, params.zeroForOne); |
||
| 165 | |||
| 166 |
if (step.tickNext <= TickMath.MIN_TICK) {
|
||
| 167 |
step.tickNext = TickMath.MIN_TICK; |
||
| 168 |
} |
||
| 169 |
if (step.tickNext >= TickMath.MAX_TICK) {
|
||
| 170 |
step.tickNext = TickMath.MAX_TICK; |
||
| 171 |
} |
||
| 172 | |||
| 173 |
step.sqrtPriceNextX96 = TickMath.getSqrtPriceAtTick(step.tickNext); |
||
| 174 | |||
| 175 |
(state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep( |
||
| 176 |
state.sqrtPriceX96, |
||
| 177 |
SwapMath.getSqrtPriceTarget(params.zeroForOne, step.sqrtPriceNextX96, params.sqrtPriceLimitX96), |
||
| 178 |
state.liquidity, |
||
| 179 |
state.amountSpecifiedRemaining, |
||
| 180 |
swapFee |
||
| 181 |
); |
||
| 182 | |||
| 183 |
if (!exactInput) {
|
||
| 184 |
unchecked {
|
||
| 185 |
state.amountSpecifiedRemaining -= step.amountOut.toInt256(); |
||
| 186 |
} |
||
| 187 |
state.amountCalculated -= (step.amountIn + step.feeAmount).toInt256(); |
||
| 188 |
} else {
|
||
| 189 |
unchecked {
|
||
| 190 |
state.amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256(); |
||
| 191 |
} |
||
| 192 |
state.amountCalculated += step.amountOut.toInt256(); |
||
| 193 |
} |
||
| 194 |
if (protocolFee > 0) {
|
||
| 195 |
unchecked {
|
||
| 196 |
// step.amountIn does not include the swap fee, as it's already been taken from it, |
||
| 197 |
// so add it back to get the total amountIn and use that to calculate the amount of fees owed to the protocol |
||
| 198 |
// this line cannot overflow due to limits on the size of protocolFee and params.amountSpecified |
||
| 199 |
uint256 delta = (step.amountIn + step.feeAmount) * protocolFee / ProtocolFeeLibrary.PIPS_DENOMINATOR; |
||
| 200 |
// subtract it from the total fee and add it to the protocol fee |
||
| 201 |
//emit LogUint256("protocol fee delta", delta);
|
||
| 202 |
step.feeAmount -= delta; |
||
| 203 |
feeForProtocol += delta; |
||
| 204 |
} |
||
| 205 |
} |
||
| 206 | |||
| 207 |
feeForLp += step.feeAmount; |
||
| 208 |
// skip fee growth calc, don't care |
||
| 209 |
if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
|
||
| 210 |
// if the tick is initialized, run the tick transition |
||
| 211 |
if (step.initialized) {
|
||
| 212 | |||
| 213 |
int128 liquidityNet = TickInfos[step.tickNext].liquidityNet; |
||
| 214 |
// if we're moving leftward, we interpret liquidityNet as the opposite sign |
||
| 215 |
// safe because liquidityNet cannot be type(int128).min |
||
| 216 |
unchecked {
|
||
| 217 |
if (params.zeroForOne) liquidityNet = -liquidityNet; |
||
| 218 |
} |
||
| 219 |
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); |
||
| 220 |
} |
||
| 221 |
state.tick = params.zeroForOne ? step.tickNext - 1 : step.tickNext; |
||
| 222 |
|
||
| 223 |
} else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {
|
||
| 224 |
// recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved |
||
| 225 |
state.tick = TickMath.getTickAtSqrtPrice(state.sqrtPriceX96); |
||
| 226 |
} |
||
| 227 |
} |
||
| 228 | |||
| 229 |
return (protocolFee,feeForLp); |
||
| 230 |
} |
||
| 231 | |||
| 232 |
/// @notice This code reproduces parts of Pool.modifyLiquidity and Pool.updateTick. |
||
| 233 |
/// Some of the logic is rewritten because we don't have to concern ourselves with |
||
| 234 |
/// liquidity removal. Every time this function is called, we're fully reconstructing the state. |
||
| 235 |
function _updateTickBitmapProxy(PoolKey memory pool) private {
|
||
| 236 |
_deleteTickBitmapProxy(); |
||
| 237 |
_deleteTickInfos(); |
||
| 238 | |||
| 239 |
PositionInfo[] storage positions = PoolPositions[pool.toId()]; |
||
| 240 |
for(uint i=0; i<positions.length; i++) {
|
||
| 241 |
PositionInfo memory position = positions[i]; |
||
| 242 |
if (position.liquidity == 0) {
|
||
| 243 |
continue; |
||
| 244 |
} |
||
| 245 |
if( !TickInfoInitialized[position.tickLower]) {
|
||
| 246 |
TickInfoIndexes.push(position.tickLower); |
||
| 247 |
TickInfoInitialized[position.tickLower] = true; |
||
| 248 |
TickBitmapProxy.flipTick(position.tickLower, pool.tickSpacing); |
||
| 249 |
TickBitmapIndexes.push(TickDescr(position.tickLower,pool.tickSpacing)); |
||
| 250 |
TickInfos[position.tickLower] = TickInfoUnpacked({
|
||
| 251 |
liquidityGross: 0, |
||
| 252 |
liquidityNet: 0 |
||
| 253 |
}); |
||
| 254 |
} |
||
| 255 |
|
||
| 256 |
TickInfos[position.tickLower].liquidityGross += position.liquidity; |
||
| 257 |
TickInfos[position.tickLower].liquidityNet = TickInfos[position.tickLower].liquidityNet + int128(position.liquidity); |
||
| 258 |
|
||
| 259 |
if( !TickInfoInitialized[position.tickUpper]) {
|
||
| 260 |
TickInfoIndexes.push(position.tickUpper); |
||
| 261 |
TickInfoInitialized[position.tickUpper] = true; |
||
| 262 |
TickBitmapProxy.flipTick(position.tickUpper, pool.tickSpacing); |
||
| 263 |
TickBitmapIndexes.push(TickDescr(position.tickUpper,pool.tickSpacing)); |
||
| 264 |
TickInfos[position.tickUpper] = TickInfoUnpacked({
|
||
| 265 |
liquidityGross: 0, |
||
| 266 |
liquidityNet: 0 |
||
| 267 |
}); |
||
| 268 |
} |
||
| 269 |
TickInfos[position.tickUpper].liquidityGross += position.liquidity; |
||
| 270 |
TickInfos[position.tickUpper].liquidityNet = TickInfos[position.tickUpper].liquidityNet - int128(position.liquidity); |
||
| 271 |
} |
||
| 272 |
} |
||
| 273 | |||
| 274 | |||
| 275 |
function _deleteTickBitmapProxy() private {
|
||
| 276 |
for(uint i=0; i<TickBitmapIndexes.length; i++) {
|
||
| 277 |
TickDescr memory tickDescr = TickBitmapIndexes[i]; |
||
| 278 |
TickBitmapProxy.flipTick(tickDescr.tick, tickDescr.tickSpacing); |
||
| 279 |
} |
||
| 280 |
delete TickBitmapIndexes; |
||
| 281 |
} |
||
| 282 | |||
| 283 |
function _deleteTickInfos() private {
|
||
| 284 |
for(uint i=0; i<TickInfoIndexes.length; i++) {
|
||
| 285 |
delete TickInfos[TickInfoIndexes[i]]; |
||
| 286 |
delete TickInfoInitialized[TickInfoIndexes[i]]; |
||
| 287 |
} |
||
| 288 |
delete TickInfoIndexes; |
||
| 289 |
} |
||
| 290 | |||
| 291 |
/// @notice calculate the expected fee growth delta, accounting for overflow. |
||
| 292 |
/// This doesn't actually touch the state machine, but it makes more sense to have it herer than in ActionFuzzBase. |
||
| 293 |
function _calculateExpectedFeeGrowth(uint256 feeGrowthDeltaX128, uint256 prevFeeGrowthX128) internal returns (uint256) {
|
||
| 294 |
// we could just do this as unchecked math, but it's nice to verify our assumptions. |
||
| 295 |
uint256 growthOverheadX128 = type(uint256).max - prevFeeGrowthX128; |
||
| 296 |
emit LogUint256("prev fee growth", prevFeeGrowthX128);
|
||
| 297 |
emit LogUint256("growth overhead", growthOverheadX128);
|
||
| 298 |
emit LogUint256("fee growth delta", feeGrowthDeltaX128);
|
||
| 299 |
uint256 feeGrowthExpectedX128; |
||
| 300 |
if( feeGrowthDeltaX128 > growthOverheadX128){
|
||
| 301 |
emit LogString("Fee growth is going to overflow");
|
||
| 302 |
// overflow case |
||
| 303 |
feeGrowthExpectedX128 = feeGrowthDeltaX128 - growthOverheadX128 - 1; |
||
| 304 |
} else {
|
||
| 305 |
emit LogString("Fee growth isn't overflowing");
|
||
| 306 |
// normal case |
||
| 307 |
feeGrowthExpectedX128 = prevFeeGrowthX128 + feeGrowthDeltaX128; |
||
| 308 |
} |
||
| 309 |
return feeGrowthExpectedX128; |
||
| 310 |
} |
||
| 311 | |||
| 312 |
} |
| Lines covered: | 0 / 27 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract BurnActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 | |||
| 27 |
address _burnFromActor; |
||
| 28 |
Currency _burnReserveCurrency; |
||
| 29 |
uint256 _burnAmount; |
||
| 30 |
int256 _burnSenderCurrencyDeltaBefore; |
||
| 31 |
uint256 _burnFromActorBalanceBefore; |
||
| 32 | |||
| 33 | |||
| 34 |
function addBurn(address from, uint8 curIdx, uint256 amount) public {
|
||
| 35 |
Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)]; |
||
| 36 | |||
| 37 |
bytes memory burnParams = abi.encode(from, currency, amount); |
||
| 38 |
bytes memory beforeBurnCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_BURN, burnParams); |
||
| 39 | |||
| 40 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 41 |
params.push(beforeBurnCbParams); |
||
| 42 | |||
| 43 |
actions.push(Actions.BURN); |
||
| 44 |
params.push(burnParams); |
||
| 45 | |||
| 46 |
bytes memory afterBurnCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_BURN, new bytes(0)); |
||
| 47 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 48 |
params.push(afterBurnCbParam); |
||
| 49 |
} |
||
| 50 | |||
| 51 | |||
| 52 |
function _beforeBurn(bytes memory preBurnParams) internal {
|
||
| 53 |
(_burnFromActor, _burnReserveCurrency, _burnAmount) = abi.decode(preBurnParams, (address, Currency, uint256)); |
||
| 54 |
_burnSenderCurrencyDeltaBefore = manager.currencyDelta(address(actionsRouter), _burnReserveCurrency); |
||
| 55 |
_burnFromActorBalanceBefore = manager.balanceOf(_burnFromActor, _burnReserveCurrency.toId()); |
||
| 56 |
emit LogUint256("burn from actor balance", _burnFromActorBalanceBefore);
|
||
| 57 |
_verifyGlobalProperties(address(actionsRouter),_burnReserveCurrency); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
function _afterBurn() internal {
|
||
| 61 |
int256 senderNewCurrencyDelta = manager.currencyDelta(address(actionsRouter), _burnReserveCurrency); |
||
| 62 |
int256 expectedBurnAmount = senderNewCurrencyDelta - _burnSenderCurrencyDeltaBefore; |
||
| 63 |
|
||
| 64 |
// UNI-SETTLE-4 |
||
| 65 |
assertGte(expectedBurnAmount, 0, "After a burn, the sender's currency delta should increase to reflect the decreased debt."); |
||
| 66 |
// UNI-SETTLE-5 (strong version of 4) |
||
| 67 |
assertEq(uint256(expectedBurnAmount), _burnAmount, "After a burn, the difference between the sender's previous and new currency delta should equal the burn amount"); |
||
| 68 | |||
| 69 |
uint256 newRecipientBalance = manager.balanceOf(_burnFromActor, _burnReserveCurrency.toId()); |
||
| 70 |
// UNI-SETTLE-6 |
||
| 71 |
assertLte(newRecipientBalance, _burnFromActorBalanceBefore, "After a burn, the from actor's balance should decrease to reflect the burned amount"); |
||
| 72 | |||
| 73 |
// note: it would be really nice to abstract away some of this overflow checking relationship to reduce the number of meaningless properties. |
||
| 74 |
// property math? |
||
| 75 |
emit LogUint256("new recipient balance", newRecipientBalance);
|
||
| 76 |
uint256 fromActorDelta = _burnFromActorBalanceBefore - newRecipientBalance; |
||
| 77 |
// UNI-SETTLE-7 |
||
| 78 |
assertEq(fromActorDelta, _burnAmount, "After a burn, the difference between the from actor's previous and new balance should equal the burn amount"); |
||
| 79 | |||
| 80 |
_addToActorsCredits(address(actionsRouter), _burnReserveCurrency, _burnAmount); |
||
| 81 |
_verifyGlobalProperties(address(actionsRouter),_burnReserveCurrency); |
||
| 82 |
} |
||
| 83 | |||
| 84 | |||
| 85 |
} |
| Lines covered: | 0 / 20 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract ClearActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 | |||
| 27 |
Currency _clearCurrency; |
||
| 28 |
uint256 _clearAmount; |
||
| 29 |
int256 _clearActorCurrencyDeltaBefore; |
||
| 30 | |||
| 31 |
function addClear(uint8 curIdx, uint256 amount) public {
|
||
| 32 |
Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)]; |
||
| 33 | |||
| 34 |
bytes memory clearParams = abi.encode(currency, amount, false, ""); |
||
| 35 |
bytes memory beforeClearCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_CLEAR, clearParams); |
||
| 36 | |||
| 37 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 38 |
params.push(beforeClearCbParams); |
||
| 39 | |||
| 40 |
|
||
| 41 |
actions.push(Actions.CLEAR); |
||
| 42 |
params.push(clearParams); |
||
| 43 |
bytes memory afterClearCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_CLEAR, new bytes(0)); |
||
| 44 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 45 |
params.push(afterClearCbParam); |
||
| 46 |
} |
||
| 47 | |||
| 48 | |||
| 49 |
function _beforeClear(bytes memory preClearParams) internal {
|
||
| 50 |
(_clearCurrency, _clearAmount,,) = abi.decode(preClearParams, (Currency, uint256, bool, string)); |
||
| 51 |
_clearActorCurrencyDeltaBefore = manager.currencyDelta(address(actionsRouter), _clearCurrency); |
||
| 52 | |||
| 53 |
_verifyGlobalProperties(address(actionsRouter),_clearCurrency); |
||
| 54 |
} |
||
| 55 | |||
| 56 |
function _afterClear() internal {
|
||
| 57 |
int256 actorCurrencyDeltaAfter = manager.currencyDelta(address(actionsRouter), _clearCurrency); |
||
| 58 | |||
| 59 |
int256 actorCurrencyDelta = _clearActorCurrencyDeltaBefore - actorCurrencyDeltaAfter; |
||
| 60 |
// UNI-SETTLE-12 |
||
| 61 |
assertGte(actorCurrencyDelta, 0, "After a clear, the actor's currency delta should go down or be equal to zero."); |
||
| 62 |
// UNI-SETTLE-13 |
||
| 63 |
assertEq(uint256(actorCurrencyDelta), _clearAmount, "After a clear, the actor's currency delta should be equal to the amount cleared."); |
||
| 64 | |||
| 65 | |||
| 66 |
_addToActorsDebts(address(actionsRouter), _clearCurrency, _clearAmount); |
||
| 67 |
_verifyGlobalProperties(address(actionsRouter),_clearCurrency); |
||
| 68 |
} |
||
| 69 | |||
| 70 | |||
| 71 |
} |
||
| 72 | |||
| 73 |
| Lines covered: | 0 / 40 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 10 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 11 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 12 |
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {FullMath} from "src/libraries/FullMath.sol";
|
||
| 15 | |||
| 16 |
contract DonateActionProps is ActionFuzzBase {
|
||
| 17 |
using PoolIdLibrary for PoolKey; |
||
| 18 |
using StateLibrary for IPoolManager; |
||
| 19 |
using CurrencyLibrary for Currency; |
||
| 20 |
using TransientStateLibrary for IPoolManager; |
||
| 21 | |||
| 22 |
PoolKey _donatePoolKey; |
||
| 23 |
uint256 _donateAmount0; |
||
| 24 |
uint256 _donateAmount1; |
||
| 25 |
uint256 _feeGrowthGlobal0X128Before; |
||
| 26 |
uint256 _feeGrowthGlobal1X128Before; |
||
| 27 | |||
| 28 |
function addDonate(uint8 poolIdx, uint256 amount0, uint256 amount1) public {
|
||
| 29 |
PoolKey memory pk = _clampToValidPool(poolIdx); |
||
| 30 |
bytes memory donateParam = abi.encode(pk, amount0, amount1); |
||
| 31 | |||
| 32 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 33 |
bytes memory beforeDonateCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_DONATE, donateParam); |
||
| 34 |
params.push(beforeDonateCbParam); |
||
| 35 | |||
| 36 |
actions.push(Actions.DONATE); |
||
| 37 |
params.push(donateParam); |
||
| 38 | |||
| 39 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 40 |
bytes memory afterDonateCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_DONATE, new bytes(0)); |
||
| 41 |
params.push(afterDonateCbParam); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function _beforeDonate(bytes memory preDonateParam) internal {
|
||
| 45 |
(_donatePoolKey, _donateAmount0, _donateAmount1) = abi.decode(preDonateParam, (PoolKey, uint256, uint256)); |
||
| 46 | |||
| 47 |
(_feeGrowthGlobal0X128Before, _feeGrowthGlobal1X128Before) = manager.getFeeGrowthGlobals(_donatePoolKey.toId()); |
||
| 48 |
_verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency0); |
||
| 49 |
_verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency1); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function _afterDonate(BalanceDelta delta) internal {
|
||
| 53 |
// UNI-DONATE-6 |
||
| 54 |
assertLte(delta.amount0(), 0, "A donate() call must not return a positive BalanceDelta for currency0"); |
||
| 55 |
// UNI-DONATE-7 |
||
| 56 |
assertLte(delta.amount1(), 0, "A donate() call must not return a positive BalanceDelta for currency1"); |
||
| 57 | |||
| 58 |
// UNI-DONATE-8 |
||
| 59 |
assertEq(_donateAmount0, uint128(-delta.amount0()), "The donate() call BalanceDelta must match the amount donated for amount0"); |
||
| 60 |
// UNI-DONATE-9 |
||
| 61 |
assertEq(_donateAmount1, uint128(-delta.amount1()), "The donate() call BalanceDelta must match the amount donated for amount1"); |
||
| 62 | |||
| 63 |
PoolId donatePoolId = _donatePoolKey.toId(); |
||
| 64 |
uint128 liquidity = manager.getLiquidity(donatePoolId); |
||
| 65 |
|
||
| 66 |
uint256 feeGrowthDelta0X128 = FullMath.mulDiv(uint256(uint128(-delta.amount0())), FixedPoint128.Q128, liquidity); |
||
| 67 |
uint256 feeGrowthDelta1X128 = FullMath.mulDiv(uint256(uint128(-delta.amount1())), FixedPoint128.Q128, liquidity); |
||
| 68 | |||
| 69 |
uint256 feeGrowth0X128Expected = _calculateExpectedFeeGrowth(feeGrowthDelta0X128, _feeGrowthGlobal0X128Before); |
||
| 70 |
uint256 feeGrowth1X128Expected = _calculateExpectedFeeGrowth(feeGrowthDelta1X128, _feeGrowthGlobal1X128Before); |
||
| 71 |
|
||
| 72 | |||
| 73 |
(uint256 feeGrowth0AfterX128, uint256 feeGrowth1AfterX128) = manager.getFeeGrowthGlobals(donatePoolId); |
||
| 74 |
if (liquidity > 0 ) {
|
||
| 75 |
if(_donateAmount0 > 0) {
|
||
| 76 |
// UNI-DONATE-1 |
||
| 77 |
assertEq(feeGrowth0X128Expected, feeGrowth0AfterX128 , "After a donation with a non-zero amount0, the pool's feeGrowthGlobal0X128 be equal to the amount0 BalanceDelta, accounting for overflows."); |
||
| 78 |
} else {
|
||
| 79 |
// UNI-DONATE-3 |
||
| 80 |
assertEq(_feeGrowthGlobal0X128Before, feeGrowth0AfterX128, "After a donation with a zero amount0, the pool's feeGrowthGlobal0X128 should not change."); |
||
| 81 |
} |
||
| 82 | |||
| 83 |
if(_donateAmount1 > 0) {
|
||
| 84 |
// UNI-DONATE-2 |
||
| 85 |
assertEq(feeGrowth1X128Expected, feeGrowth1AfterX128, "After a donation with a non-zero amount1, the pool's feeGrowthGlobal0X128 be equal to the amount1 BalanceDelta, accounting for overflows."); |
||
| 86 |
} else {
|
||
| 87 |
// UNI-DONATE-4 |
||
| 88 |
assertEq(_feeGrowthGlobal1X128Before, feeGrowth1AfterX128, "After a donation with a zero amount1, the pool's feeGrowthGlobal1X128 should not change."); |
||
| 89 |
} |
||
| 90 |
} else {
|
||
| 91 |
// fee growth should not have changed |
||
| 92 |
// UNI-DONATE-5 |
||
| 93 |
assertWithMsg(false, "Donating to a pool with zero liquidity should result in a revert."); |
||
| 94 |
} |
||
| 95 | |||
| 96 |
/* Update virtual pool reserves */ |
||
| 97 | |||
| 98 |
_updateCurrencyDelta(address(actionsRouter), _donatePoolKey.currency0, delta.amount0()); |
||
| 99 |
_updateCurrencyDelta(address(actionsRouter), _donatePoolKey.currency1, delta.amount1()); |
||
| 100 | |||
| 101 |
SingletonLPFees[_donatePoolKey.currency0] = _deltaAdd(SingletonLPFees[_donatePoolKey.currency0], int256(_donateAmount0)); |
||
| 102 |
SingletonLPFees[_donatePoolKey.currency1] = _deltaAdd(SingletonLPFees[_donatePoolKey.currency1], int256(_donateAmount1)); |
||
| 103 | |||
| 104 | |||
| 105 |
_verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency0); |
||
| 106 |
_verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency1); |
||
| 107 |
} |
||
| 108 |
} |
| Lines covered: | 0 / 54 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 10 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 11 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 12 |
import {Pool} from "src/libraries/Pool.sol";
|
||
| 13 |
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
|
||
| 14 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 15 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 16 | |||
| 17 | |||
| 18 |
contract InitializeActionProps is ActionFuzzBase {
|
||
| 19 |
using PoolIdLibrary for PoolKey; |
||
| 20 |
using CurrencyLibrary for Currency; |
||
| 21 |
using StateLibrary for IPoolManager; |
||
| 22 | |||
| 23 |
function addInitialize(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee) public {
|
||
| 24 |
Currency c1; |
||
| 25 |
Currency c2; |
||
| 26 |
(c1, c2) = _clampToValidCurrencies(currency1I, currency2I); |
||
| 27 |
int24 tickSpacingClamped = int24(clampBetween(tickSpacing,TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING)); |
||
| 28 |
emit LogInt256("tickSpacingClamped", tickSpacingClamped);
|
||
| 29 | |||
| 30 |
uint256 initialPrice = clampBetween(startPrice, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE-1); |
||
| 31 |
emit LogUint256("initialPrice", initialPrice);
|
||
| 32 |
|
||
| 33 |
uint256 initialFee = clampBetween(fee, 0, ProtocolFeeLibrary.PIPS_DENOMINATOR); |
||
| 34 |
emit LogUint256("initialFee", initialFee);
|
||
| 35 | |||
| 36 |
PoolKey memory k = PoolKey(c1, c2, uint24(initialFee), tickSpacingClamped, IHooks(address(0))); |
||
| 37 |
PoolId id = k.toId(); |
||
| 38 |
require(!PoolInitialized[id]); |
||
| 39 |
// todo: add revert catcher from e2e harness |
||
| 40 |
try manager.initialize(k, uint160(initialPrice), new bytes(0)) {
|
||
| 41 |
} catch (bytes memory b) {
|
||
| 42 |
emit LogBytes("Error", b);
|
||
| 43 |
// UNI-INIT-1 |
||
| 44 |
assertWithMsg(false, "initialize() should not revert when it is passed valid parameters (tick spacing, price, fee, pool key, non-existing poo)"); |
||
| 45 |
} |
||
| 46 |
|
||
| 47 | |||
| 48 |
DeployedPools.push(k); |
||
| 49 |
PoolInitialized[id] = true; |
||
| 50 |
} |
||
| 51 | |||
| 52 | |||
| 53 |
function addInitializeUnconstrained(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee) public {
|
||
| 54 |
Currency c1; |
||
| 55 |
Currency c2; |
||
| 56 |
(c1, c2) = _clampToValidCurrencies(currency1I, currency2I); |
||
| 57 | |||
| 58 |
PoolKey memory k = PoolKey(c1, c2, uint24(fee), tickSpacing, IHooks(address(0))); |
||
| 59 |
PoolId id = k.toId(); |
||
| 60 | |||
| 61 |
bool poolinitialized = PoolInitialized[id]; |
||
| 62 |
int24 tick; |
||
| 63 | |||
| 64 |
try manager.initialize(k, uint160(startPrice), new bytes(0)) returns (int24 t) {
|
||
| 65 |
tick = t; |
||
| 66 |
} catch (bytes memory data) {
|
||
| 67 |
// UNI-INIT-2 |
||
| 68 |
if (bytes4(data) == Pool.PoolAlreadyInitialized.selector){
|
||
| 69 |
// allowable exception iff poolInitialized |
||
| 70 |
assertWithMsg(poolinitialized, "initialize() must not throw PoolAlreadyInitialized() when there is no pre-existing pool initialized with the same PoolKey"); |
||
| 71 |
return; |
||
| 72 |
} |
||
| 73 |
// UNI-INIT-3 |
||
| 74 |
if (bytes4(data) == TickMath.InvalidSqrtPrice.selector){
|
||
| 75 |
// allowable exception iff initialPrice is outside the valid range |
||
| 76 |
assertWithMsg(startPrice < TickMath.MIN_SQRT_PRICE || startPrice > TickMath.MAX_SQRT_PRICE-1, "initialize() must not throw InvalidSqrtPrice() when provided a price within the valid range"); |
||
| 77 |
return; |
||
| 78 |
} |
||
| 79 |
// UNI-INIT-4 |
||
| 80 |
if (bytes4(data) == LPFeeLibrary.LPFeeTooLarge.selector){
|
||
| 81 |
// allowable exception iff fee is larger than 1_000_000 |
||
| 82 |
assertGt(fee, 1_000_000, "initialize() must not throw LPFeeTooLarge() when the fee is in the valid range"); |
||
| 83 |
return; |
||
| 84 |
} |
||
| 85 | |||
| 86 |
// UNI-INIT-5 |
||
| 87 |
if (bytes4(data) == IPoolManager.TickSpacingTooLarge.selector){
|
||
| 88 |
// allowable exception iff tick spacing is >max |
||
| 89 |
assertGt(tickSpacing, TickMath.MAX_TICK_SPACING, "initialize() must not throw TickSpacingTooLarge() when the tick spacing is in the valid range"); |
||
| 90 |
return; |
||
| 91 |
} |
||
| 92 | |||
| 93 |
// UNI-INIT-6 |
||
| 94 |
if (bytes4(data) == IPoolManager.TickSpacingTooSmall.selector){
|
||
| 95 |
// allowable exception iff tick spacing is <min |
||
| 96 |
assertLt(tickSpacing, TickMath.MIN_TICK_SPACING , "initialize() must not throw TickSpacingTooSmall() when the tick spacing is in the valid range"); |
||
| 97 |
return; |
||
| 98 |
} |
||
| 99 |
// todo: revisit for other types of errors |
||
| 100 |
require(false); |
||
| 101 |
} |
||
| 102 | |||
| 103 | |||
| 104 |
// UNI-INIT-7 |
||
| 105 |
assertWithMsg(!poolinitialized, "initialize() must revert if the provided pool key is already initialized"); |
||
| 106 |
// UNI-INIT-8 |
||
| 107 |
assertGte(tick, TickMath.MIN_TICK, "initialize() must construct a pool whose tick is greater than or equal to MIN_TICK"); |
||
| 108 |
// UNI-INIT-9 |
||
| 109 |
assertLte(tick, TickMath.MAX_TICK, "initialize() must construct a pool whose tick is less than or equal to MAX_TICK"); |
||
| 110 | |||
| 111 |
(uint160 price, ,,) = manager.getSlot0(id); |
||
| 112 |
// UNI-INIT-10 |
||
| 113 |
assertNeq(price, 0, "initialize() must never create a pool with an initial sqrtPrice of zero."); |
||
| 114 | |||
| 115 |
DeployedPools.push(k); |
||
| 116 |
PoolInitialized[id] = true; |
||
| 117 |
} |
||
| 118 | |||
| 119 | |||
| 120 |
} |
| Lines covered: | 0 / 28 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract MintActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 | |||
| 27 |
address _mintRecipient; |
||
| 28 |
Currency _mintReserveCurrency; |
||
| 29 |
uint256 _mintAmount; |
||
| 30 |
int256 _mintSenderCurrencyDeltaBefore; |
||
| 31 |
uint256 _mintRecipientBalanceBefore; |
||
| 32 | |||
| 33 | |||
| 34 |
function addMint(address recipient, uint8 curIdx, uint256 amount) public {
|
||
| 35 |
Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)]; |
||
| 36 | |||
| 37 |
bytes memory mintParams = abi.encode(recipient, currency, amount); |
||
| 38 |
bytes memory beforeMintCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_MINT, mintParams); |
||
| 39 | |||
| 40 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 41 |
params.push(beforeMintCbParams); |
||
| 42 | |||
| 43 |
actions.push(Actions.MINT); |
||
| 44 |
params.push(mintParams); |
||
| 45 | |||
| 46 |
bytes memory afterMintCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_MINT, new bytes(0)); |
||
| 47 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 48 |
params.push(afterMintCbParam); |
||
| 49 |
} |
||
| 50 | |||
| 51 | |||
| 52 | |||
| 53 |
function _beforeMint(bytes memory preMintParams) internal {
|
||
| 54 |
(_mintRecipient, _mintReserveCurrency, _mintAmount) = abi.decode(preMintParams, (address, Currency, uint256)); |
||
| 55 |
_mintSenderCurrencyDeltaBefore = manager.currencyDelta(address(actionsRouter), _mintReserveCurrency); |
||
| 56 |
_mintRecipientBalanceBefore = manager.balanceOf(_mintRecipient, _mintReserveCurrency.toId()); |
||
| 57 |
_verifyGlobalProperties(address(actionsRouter), _mintReserveCurrency); |
||
| 58 |
emit LogUint256("mint amount", _mintAmount);
|
||
| 59 |
emit LogInt256("mint sender currency delta", _mintSenderCurrencyDeltaBefore);
|
||
| 60 |
} |
||
| 61 | |||
| 62 |
function _afterMint() internal {
|
||
| 63 |
int256 actorCurrencyDeltaAfter = manager.currencyDelta(address(actionsRouter), _mintReserveCurrency); |
||
| 64 |
emit LogInt256("mint sender currency delta after", actorCurrencyDeltaAfter);
|
||
| 65 |
int256 expectedDeltaMint = _mintSenderCurrencyDeltaBefore - actorCurrencyDeltaAfter; |
||
| 66 |
// UNI-SETTLE-8 |
||
| 67 |
assertGte(expectedDeltaMint, 0, "After a mint, the sender's currency delta should decrease to reflect increased debt."); |
||
| 68 |
// UNI-SETTLE-9 |
||
| 69 |
assertEq(uint256(expectedDeltaMint), _mintAmount, "After a mint, the difference between the sender's previous and new currency delta should match the mint amount"); |
||
| 70 | |||
| 71 |
uint256 newRecipientBalance = manager.balanceOf(_mintRecipient, _mintReserveCurrency.toId()); |
||
| 72 |
//UNI-SETTLE-10 |
||
| 73 |
assertGte(newRecipientBalance, _mintRecipientBalanceBefore, "After a mint, the recipient's ERC6909 balance should increase"); |
||
| 74 | |||
| 75 |
uint256 recipientDelta = newRecipientBalance - _mintRecipientBalanceBefore; |
||
| 76 |
// UNI-SETTLE-11 |
||
| 77 |
assertEq(recipientDelta, _mintAmount, "After a mint, the recipient's ERC6909 balance should increase by the mint amount"); |
||
| 78 | |||
| 79 |
_addToActorsDebts(address(actionsRouter), _mintReserveCurrency, _mintAmount); |
||
| 80 |
_verifyGlobalProperties(address(actionsRouter), _mintReserveCurrency); |
||
| 81 | |||
| 82 |
} |
||
| 83 | |||
| 84 | |||
| 85 |
} |
| Lines covered: | 0 / 101 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {V4StateMachine} from "test/trailofbits/V4StateMachine.sol";
|
||
| 6 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 7 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 8 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 9 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 12 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 13 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 14 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 15 |
import {Position} from "src/libraries/Position.sol";
|
||
| 16 |
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
|
||
| 17 |
import {FullMath} from "src/libraries/FullMath.sol";
|
||
| 18 | |||
| 19 |
contract ModifyPositionActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using TransientStateLibrary for IPoolManager; |
||
| 23 |
using StateLibrary for IPoolManager; |
||
| 24 | |||
| 25 |
struct ExistingPosition {
|
||
| 26 |
Position.Info positionInfo; |
||
| 27 |
} |
||
| 28 | |||
| 29 |
PoolKey _modifyPoolKey; |
||
| 30 |
bytes32 _modifySalt; |
||
| 31 |
int128 _modifyLiqDelta; |
||
| 32 |
int24 _modifyLowTick; |
||
| 33 |
int24 _modifyHighTick; |
||
| 34 |
uint256 _modifyFeeGrowthGlobal0; |
||
| 35 |
uint256 _modifyFeeGrowthGlobal1; |
||
| 36 | |||
| 37 |
uint128 _modifyPositionLiquidityBefore; |
||
| 38 |
uint256 _modifyFeeGrowthInside0Before; |
||
| 39 |
uint256 _modifyFeeGrowthInside1Before; |
||
| 40 | |||
| 41 |
uint256 _modifyFeesExpectedDelta0X128; |
||
| 42 |
uint256 _modifyFeesExpectedDelta1X128; |
||
| 43 |
uint128 _modifyLiquidityExpected; |
||
| 44 | |||
| 45 |
Position.Info _modifyPositionInfoBefore; |
||
| 46 | |||
| 47 | |||
| 48 | |||
| 49 |
function addModifyPosition(uint8 poolIdx, int24 lowTick, int24 highTick, int128 liqDelta, uint256 salt) public {
|
||
| 50 |
// potential props: StateLibrary.getTickLiquidity |
||
| 51 |
// StateLibrary.getLiquidity |
||
| 52 |
// getPositionLiquidity |
||
| 53 | |||
| 54 | |||
| 55 |
// getModifyPositionBefore |
||
| 56 |
// snapshot liquidity of position |
||
| 57 |
// snapshot liquidity of pool |
||
| 58 |
// snapshot fees |
||
| 59 |
// snapshot price |
||
| 60 |
// snapshot tick |
||
| 61 | |||
| 62 | |||
| 63 | |||
| 64 |
// getModifyPositionAfter |
||
| 65 |
|
||
| 66 |
PoolKey memory pk = _clampToValidPool(poolIdx); |
||
| 67 |
|
||
| 68 |
(lowTick, highTick) = _clampToUsableTicks(lowTick, highTick, pk); |
||
| 69 |
bytes memory modifyParam = abi.encode(pk, lowTick, highTick, liqDelta, bytes32(salt)); |
||
| 70 | |||
| 71 |
bytes memory beforeModifyCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_MODIFY_POSITION, modifyParam); |
||
| 72 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 73 |
params.push(beforeModifyCbParam); |
||
| 74 | |||
| 75 |
actions.push(Actions.MODIFY_POSITION); |
||
| 76 |
params.push(modifyParam); |
||
| 77 | |||
| 78 |
bytes memory afterModifyCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_MODIFY_POSITION, new bytes(0)); |
||
| 79 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 80 |
params.push(afterModifyCbParam); |
||
| 81 |
} |
||
| 82 | |||
| 83 |
function _beforeModifyPosition(bytes memory preModifyParams) internal {
|
||
| 84 |
(_modifyPoolKey, _modifyLowTick, _modifyHighTick,_modifyLiqDelta ,_modifySalt ) = |
||
| 85 |
abi.decode(preModifyParams, (PoolKey, int24, int24, int128, bytes32)); |
||
| 86 | |||
| 87 |
(_modifyFeeGrowthGlobal0, _modifyFeeGrowthGlobal1) = manager.getFeeGrowthGlobals(_modifyPoolKey.toId()); |
||
| 88 | |||
| 89 |
(_modifyPositionLiquidityBefore, _modifyFeeGrowthInside0Before, _modifyFeeGrowthInside1Before) = manager.getPositionInfo( |
||
| 90 |
_modifyPoolKey.toId(), |
||
| 91 |
_modifySalt |
||
| 92 |
); |
||
| 93 |
_modifyPositionInfoBefore = manager.getPosition(_modifyPoolKey.toId(), address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt); |
||
| 94 |
(_modifyFeesExpectedDelta0X128, _modifyFeesExpectedDelta1X128, _modifyLiquidityExpected) = _calculateExpectedFeeDelta(_modifyPoolKey.toId(), _modifyLiqDelta, _modifyLowTick, _modifyHighTick, address(actionsRouter), _modifySalt); |
||
| 95 | |||
| 96 |
_verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency0); |
||
| 97 |
_verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency1); |
||
| 98 |
_verifyStateLibraryGetterEquivalence(); |
||
| 99 |
} |
||
| 100 | |||
| 101 |
function _afterModifyPosition(BalanceDelta callerDelta, BalanceDelta feesAccrued) internal {
|
||
| 102 |
emit LogInt256("modify liquidity callerDelta amount0", callerDelta.amount0());
|
||
| 103 |
emit LogInt256("modify liquidity callerDelta amount1", callerDelta.amount1());
|
||
| 104 |
emit LogInt256("modify liquidity feesAccrued amount0", feesAccrued.amount0());
|
||
| 105 |
emit LogInt256("modify liquidity feesAccrued amount1", feesAccrued.amount1());
|
||
| 106 | |||
| 107 |
// UNI-MODLIQ-4 |
||
| 108 |
assertGte(feesAccrued.amount0(), 0, "The amount0 of fees accrued from modifyPosition() must be non-negative"); |
||
| 109 |
// UNI-MODLIQ-5 |
||
| 110 |
assertGte(feesAccrued.amount1(), 0, "The amount1 of fees accrued from modifyPosition() must be non-negative"); |
||
| 111 | |||
| 112 | |||
| 113 |
int256 principalDelta0 = callerDelta.amount0() - feesAccrued.amount0(); |
||
| 114 |
int256 principalDelta1 = callerDelta.amount1() - feesAccrued.amount1(); |
||
| 115 |
emit LogInt256("Change in amount0 principal", principalDelta0);
|
||
| 116 |
emit LogInt256("Change in amount1 principal", principalDelta1);
|
||
| 117 | |||
| 118 |
// UNI-MODLIQ-8 |
||
| 119 |
assertGte(PoolLiquidities[_modifyPoolKey.toId()].amount0, principalDelta0, "The pool must have enough currency0 to return the LP's liquidity balance"); |
||
| 120 |
// UNI-MODLIQ-9 |
||
| 121 |
assertGte(PoolLiquidities[_modifyPoolKey.toId()].amount1, principalDelta1, "The pool must have enough currency1 to return the LP's liquidity balance"); |
||
| 122 | |||
| 123 |
// assert fees == fees expected |
||
| 124 |
assertEq(uint128(feesAccrued.amount0()), _modifyFeesExpectedDelta0X128, "The amount0 of fees accrued from modifyPosition() must match the expected fee."); |
||
| 125 |
assertEq(uint128(feesAccrued.amount1()), _modifyFeesExpectedDelta1X128, "The amount1 of fees accrued from modifyPosition() must match the expected fee."); |
||
| 126 | |||
| 127 |
// UNI-MODLIQ-6 |
||
| 128 |
assertGte(SingletonLPFees[_modifyPoolKey.currency0], uint128(feesAccrued.amount0()), "The singleton must be able to credit the user for the amount of feeGrowth they are owed (amount0)"); |
||
| 129 |
// UNI-MODLIQ-7 |
||
| 130 |
assertGte(SingletonLPFees[_modifyPoolKey.currency1], uint128(feesAccrued.amount1()), "The singleton must be able to credit the user for the amount of feeGrowth they are owed (amount1)"); |
||
| 131 |
emit LogInt256("hiiisddddi", 5);
|
||
| 132 | |||
| 133 |
if(principalDelta0 > 0) {
|
||
| 134 |
// UNI-MODLIQ-10 |
||
| 135 |
assertGte(SingletonLiquidity[_modifyPoolKey.currency0], uint256(principalDelta0), "The singleton must have enough currency0 to return the LP's liquidity balance"); |
||
| 136 |
} |
||
| 137 |
if(principalDelta1 > 0){
|
||
| 138 |
// UNI-MOQLIQ-11 |
||
| 139 |
assertGte(SingletonLiquidity[_modifyPoolKey.currency1], uint256(principalDelta1), "The singleton must have enough currency1 to return the LP's liquidity balance"); |
||
| 140 |
} |
||
| 141 | |||
| 142 |
/* Update virtual pool reserves */ |
||
| 143 |
PoolLiquidities[_modifyPoolKey.toId()].amount0 -= principalDelta0; |
||
| 144 |
PoolLiquidities[_modifyPoolKey.toId()].amount1 -= principalDelta1; |
||
| 145 | |||
| 146 |
emit LogInt256("Pool Liquidity amount0 updated", PoolLiquidities[_modifyPoolKey.toId()].amount0);
|
||
| 147 |
emit LogInt256("Pool Liquidity amount1 updated", PoolLiquidities[_modifyPoolKey.toId()].amount1);
|
||
| 148 | |||
| 149 |
// Update singleton liquidity |
||
| 150 |
uint256 newSingletonLiq0 = _deltaAdd(SingletonLiquidity[_modifyPoolKey.currency0], -(principalDelta0)); |
||
| 151 |
emit LogUint256("Singleton now has this much liquidity for amount0:", newSingletonLiq0);
|
||
| 152 |
uint256 newSingletonLiq1 = _deltaAdd(SingletonLiquidity[_modifyPoolKey.currency1], -(principalDelta1)); |
||
| 153 |
emit LogUint256("Singleton now has this much liquidity for amount1:", newSingletonLiq1);
|
||
| 154 | |||
| 155 |
SingletonLiquidity[_modifyPoolKey.currency0] = newSingletonLiq0; |
||
| 156 |
SingletonLiquidity[_modifyPoolKey.currency1] = newSingletonLiq1; |
||
| 157 | |||
| 158 |
SingletonLPFees[_modifyPoolKey.currency0] -= uint128(feesAccrued.amount0()); |
||
| 159 |
SingletonLPFees[_modifyPoolKey.currency1] -= uint128(feesAccrued.amount1()); |
||
| 160 | |||
| 161 |
// do not bother using _addToActorsCredits/_addToActorsDebts since BalanceDelta is already int128 |
||
| 162 |
_updateCurrencyDelta(address(actionsRouter), _modifyPoolKey.currency0, callerDelta.amount0() ); |
||
| 163 |
_updateCurrencyDelta(address(actionsRouter), _modifyPoolKey.currency1, callerDelta.amount1() ); |
||
| 164 | |||
| 165 |
// update our positions lookup |
||
| 166 |
_updatePoolPositions(); |
||
| 167 | |||
| 168 |
_verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency0); |
||
| 169 |
_verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency1); |
||
| 170 |
} |
||
| 171 | |||
| 172 |
function _verifyStateLibraryGetterEquivalence() internal {
|
||
| 173 |
Position.Info memory positionInfo = manager.getPosition(_modifyPoolKey.toId(), address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt); |
||
| 174 | |||
| 175 |
bytes32 positionId = keccak256(abi.encodePacked(address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt)); |
||
| 176 |
(uint128 positionLiq, uint256 positionFeeGrowth0, uint256 positionFeeGrowth1) = manager.getPositionInfo( |
||
| 177 |
_modifyPoolKey.toId(), |
||
| 178 |
positionId |
||
| 179 |
); |
||
| 180 |
// UNI-MODLIQ-1 |
||
| 181 |
assertEq(positionInfo.liquidity, positionLiq, "For a specific position, getPositionInfo must return the same liquidity as getPosition"); |
||
| 182 |
// UNI-MODLIQ-2 |
||
| 183 |
assertEq(positionInfo.feeGrowthInside0LastX128, positionFeeGrowth0, "For a specific position, getPositionInfo must return the same feeGrowthInside0 as getPosition"); |
||
| 184 |
// UNI-MODLIQ-3 |
||
| 185 |
assertEq(positionInfo.feeGrowthInside1LastX128, positionFeeGrowth1, "For a specific position, getPositionInfo must return the same feeGrowthInside1 as getPosition"); |
||
| 186 |
} |
||
| 187 | |||
| 188 |
function _calculateExpectedFeeDelta(PoolId poolId, int128 liqDelta, int24 lowTick, int24 highTick, address owner, bytes32 salt) internal view returns (uint256, uint256,uint128) {
|
||
| 189 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = manager.getFeeGrowthInside(poolId, lowTick, highTick); |
||
| 190 |
Position.Info memory positionInfo = manager.getPosition(poolId, owner, lowTick, highTick, salt); |
||
| 191 | |||
| 192 |
if (liqDelta == 0 && positionInfo.liquidity == 0) {
|
||
| 193 |
// this isn't the place for checking properties |
||
| 194 |
return (0,0,0); |
||
| 195 |
} |
||
| 196 |
|
||
| 197 |
// doing this outside yul will let us indirectly check their LiquidityMath.addDelta |
||
| 198 |
uint128 liquidityExpected; |
||
| 199 |
if(liqDelta > 0) {
|
||
| 200 |
liquidityExpected = positionInfo.liquidity + uint128(liqDelta); |
||
| 201 |
} else {
|
||
| 202 |
liquidityExpected = positionInfo.liquidity - uint128(-liqDelta); |
||
| 203 |
} |
||
| 204 | |||
| 205 |
uint256 feesOwed0; |
||
| 206 |
uint256 feesOwed1; |
||
| 207 | |||
| 208 |
unchecked {
|
||
| 209 |
feesOwed0 = |
||
| 210 |
FullMath.mulDiv(feeGrowthInside0X128 - positionInfo.feeGrowthInside0LastX128, positionInfo.liquidity, FixedPoint128.Q128); |
||
| 211 |
feesOwed1 = |
||
| 212 |
FullMath.mulDiv(feeGrowthInside1X128 - positionInfo.feeGrowthInside1LastX128, positionInfo.liquidity, FixedPoint128.Q128); |
||
| 213 |
} |
||
| 214 | |||
| 215 |
return (feesOwed0, feesOwed1, liquidityExpected); |
||
| 216 |
} |
||
| 217 | |||
| 218 |
function _updatePoolPositions() internal {
|
||
| 219 |
bytes32 positionId = keccak256(abi.encodePacked(address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt)); |
||
| 220 |
(uint128 positionLiq, , ) = manager.getPositionInfo( |
||
| 221 |
_modifyPoolKey.toId(), |
||
| 222 |
positionId |
||
| 223 |
); |
||
| 224 | |||
| 225 |
bytes32 positionInfoLookup = keccak256(abi.encodePacked(_modifyPoolKey.toId(), positionId)); |
||
| 226 |
int index = PositionInfoIndex[positionInfoLookup]; |
||
| 227 |
if(index == 0) {
|
||
| 228 |
// position does not exist in list |
||
| 229 |
V4StateMachine.PositionInfo memory newPosition = V4StateMachine.PositionInfo(0, _modifyLowTick, _modifyHighTick); |
||
| 230 |
index = int(PoolPositions[_modifyPoolKey.toId()].length); |
||
| 231 |
int newPositionIdx = index; |
||
| 232 |
if (newPositionIdx == 0) {
|
||
| 233 |
newPositionIdx = -1; |
||
| 234 |
} |
||
| 235 |
PoolPositions[_modifyPoolKey.toId()].push(newPosition); |
||
| 236 |
PositionInfoIndex[positionInfoLookup] = newPositionIdx; |
||
| 237 | |||
| 238 |
} else if (index == -1) {
|
||
| 239 |
// we use -1 for the position that actually lives at index 0 |
||
| 240 |
index = 0; |
||
| 241 |
} |
||
| 242 |
emit LogInt256("setting liq for position idx", index);
|
||
| 243 |
emit LogUint256("to liquidity ", positionLiq);
|
||
| 244 | |||
| 245 |
PoolPositions[_modifyPoolKey.toId()][uint(index)].liquidity = positionLiq; |
||
| 246 |
} |
||
| 247 |
} |
| Lines covered: | 0 / 29 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {IProtocolFeeController} from "src/interfaces/IProtocolFeeController.sol";
|
||
| 18 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 19 | |||
| 20 |
contract ProtocolFeeActionProps is ActionFuzzBase {
|
||
| 21 |
using PoolIdLibrary for PoolKey; |
||
| 22 |
using CurrencyLibrary for Currency; |
||
| 23 |
using StateLibrary for IPoolManager; |
||
| 24 |
using TransientStateLibrary for IPoolManager; |
||
| 25 |
using ProtocolFeeLibrary for uint16; |
||
| 26 | |||
| 27 | |||
| 28 |
uint24 CurrentProtocolFee; |
||
| 29 | |||
| 30 |
function protocolFeeForPool(PoolKey memory) external view returns (uint24 protocolFee) {
|
||
| 31 |
return CurrentProtocolFee; |
||
| 32 |
} |
||
| 33 | |||
| 34 |
/* Setting protocol fee */ |
||
| 35 |
function _setNewProtocolFee(bytes memory setNewProtocolFeeParams) internal {
|
||
| 36 |
(PoolKey memory poolKey, uint24 amount) = abi.decode(setNewProtocolFeeParams, (PoolKey, uint24)); |
||
| 37 | |||
| 38 |
manager.setProtocolFee(poolKey, amount); |
||
| 39 |
CurrentProtocolFee = amount; |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function addSetNewProtocolFee(uint8 poolIdx, uint24 amount) public {
|
||
| 43 |
// ensure the protocol fee controller is set first |
||
| 44 |
if(address(manager.protocolFeeController()) != address(this)){
|
||
| 45 |
manager.setProtocolFeeController(IProtocolFeeController(address(this))); |
||
| 46 |
} |
||
| 47 |
PoolKey memory poolKey = _clampToValidPool(poolIdx); |
||
| 48 | |||
| 49 |
bytes memory setNewProtocolFeeParams = abi.encode(poolKey, amount); |
||
| 50 |
bytes memory setNewProtocolFeeCbParams = _encodeHarnessCallback(ActionCallbacks.SET_NEW_PROTOCOL_FEE, setNewProtocolFeeParams); |
||
| 51 | |||
| 52 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 53 |
params.push(setNewProtocolFeeCbParams); |
||
| 54 |
|
||
| 55 |
} |
||
| 56 | |||
| 57 |
/* Collecting protocol fees */ |
||
| 58 | |||
| 59 |
function _collectProtocolFees(bytes memory collectProtocolFeesParams) internal {
|
||
| 60 |
// we don't need a _before or _after since we're calling this from our harness, not ActionsRouter |
||
| 61 |
Currency currency = abi.decode(collectProtocolFeesParams, (Currency)); |
||
| 62 |
uint256 feeToCollect = manager.protocolFeesAccrued(currency); |
||
| 63 | |||
| 64 |
try manager.collectProtocolFees(address(this), currency, feeToCollect) { }
|
||
| 65 |
catch(bytes memory b) {
|
||
| 66 |
emit LogBytes("error", b);
|
||
| 67 |
// UNI-ACTION-6 |
||
| 68 |
assertWithMsg(false, "collectProtocolFees must not revert on valid input"); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
_verifyGlobalProperties(address(actionsRouter), currency); |
||
| 72 |
} |
||
| 73 | |||
| 74 |
function addCollectProtocolFees(uint8 currencyIdx) public {
|
||
| 75 |
Currency currency = Currencies[clampBetween(currencyIdx, 0, NUMBER_CURRENCIES-1)]; |
||
| 76 |
if(address(manager.protocolFeeController()) != address(this)){
|
||
| 77 |
manager.setProtocolFeeController(IProtocolFeeController(address(this))); |
||
| 78 |
} |
||
| 79 |
|
||
| 80 |
bytes memory collectProtocolFeesParams = abi.encode(currency); |
||
| 81 |
bytes memory collectProtocolFeesCbParams = _encodeHarnessCallback(ActionCallbacks.COLLECT_PROTOCOL_FEES, collectProtocolFeesParams); |
||
| 82 |
|
||
| 83 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 84 |
params.push(collectProtocolFeesCbParams); |
||
| 85 | |||
| 86 |
} |
||
| 87 |
} |
||
| 88 | |||
| 89 |
| Lines covered: | 0 / 32 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract SettleActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 | |||
| 27 |
address _settleActor; |
||
| 28 |
Currency _settleReserveCurrency; |
||
| 29 |
int256 _currencyDeltaBefore; |
||
| 30 | |||
| 31 | |||
| 32 |
function addSettle() public {
|
||
| 33 |
bytes memory beforeSettleCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SETTLE, abi.encode(address(actionsRouter))); |
||
| 34 | |||
| 35 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 36 |
params.push(beforeSettleCbParams); |
||
| 37 | |||
| 38 |
actions.push(Actions.SETTLE); |
||
| 39 |
params.push(new bytes(0)); |
||
| 40 | |||
| 41 |
bytes memory afterSettleCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SETTLE, new bytes(0)); |
||
| 42 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 43 |
params.push(afterSettleCbParam); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function addSettleFor(address addr) public {
|
||
| 47 |
bytes memory settleForParams = abi.encode(addr); |
||
| 48 | |||
| 49 |
bytes memory beforeSettleCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SETTLE, settleForParams); |
||
| 50 | |||
| 51 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 52 |
params.push(beforeSettleCbParams); |
||
| 53 | |||
| 54 |
actions.push(Actions.SETTLE_FOR); |
||
| 55 |
params.push(settleForParams); |
||
| 56 | |||
| 57 |
bytes memory afterSettleCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SETTLE, new bytes(0)); |
||
| 58 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 59 |
params.push(afterSettleCbParam); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function _beforeSettle(bytes memory preSettleParams) internal {
|
||
| 63 |
_settleActor = abi.decode(preSettleParams, (address)); |
||
| 64 |
_settleReserveCurrency = manager.getSyncedCurrency(); |
||
| 65 | |||
| 66 |
// The only reason we keep track of remittance currency separately like this is to validate our assumptions about how |
||
| 67 |
// transient storage works during runtime. |
||
| 68 |
emit LogAddress("synced currency", address(Currency.unwrap(_settleReserveCurrency)));
|
||
| 69 |
emit LogAddress("Remittance currency", address(Currency.unwrap(RemittanceCurrency)));
|
||
| 70 | |||
| 71 |
_currencyDeltaBefore = manager.currencyDelta(_settleActor, _settleReserveCurrency); |
||
| 72 |
_verifyGlobalProperties(_settleActor, _settleReserveCurrency); |
||
| 73 |
} |
||
| 74 | |||
| 75 |
function _afterSettle(uint256 paid) internal {
|
||
| 76 |
int256 currencyDeltaAfterSettle = manager.currencyDelta(_settleActor, _settleReserveCurrency); |
||
| 77 | |||
| 78 |
int256 currencyDeltaDifference = currencyDeltaAfterSettle - _currencyDeltaBefore; |
||
| 79 | |||
| 80 |
// UNI-SETTLE-1 |
||
| 81 |
assertGte(currencyDeltaDifference, 0, "The user must not be owed more tokens after a settle than they were owed before a settle."); |
||
| 82 |
// UNI-SETTLE-2 |
||
| 83 |
assertEq(currencyDeltaDifference, int256(paid), "The amount paid during a settle must be equal to the difference in the user's currency deltas before and after the settle call."); |
||
| 84 |
// UNI-SETTLE-3 |
||
| 85 |
assertEq(int256(paid), RemittanceAmount, "The amount paid during a settle must be equal to the amount of remittances paid to the singleton."); |
||
| 86 | |||
| 87 |
_addToActorsCredits(_settleActor, _settleReserveCurrency, paid); |
||
| 88 |
_verifyGlobalProperties(_settleActor, _settleReserveCurrency); |
||
| 89 |
RemittanceCurrency = CurrencyLibrary.NATIVE; |
||
| 90 |
} |
||
| 91 | |||
| 92 | |||
| 93 |
} |
||
| 94 |
| Lines covered: | 0 / 14 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract SettleNativeActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 | |||
| 27 |
address _settleNativeActor; |
||
| 28 |
uint256 _settleNativeAmount; |
||
| 29 | |||
| 30 | |||
| 31 |
function addSettleNative(uint256 amount) public {
|
||
| 32 | |||
| 33 |
bytes memory beforeSettleCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SETTLE_NATIVE, abi.encode(address(actionsRouter), amount)); |
||
| 34 | |||
| 35 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 36 |
params.push(beforeSettleCbParams); |
||
| 37 | |||
| 38 |
actions.push(Actions.SETTLE_NATIVE); |
||
| 39 |
params.push(abi.encode(amount)); |
||
| 40 | |||
| 41 |
bytes memory afterSettleCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SETTLE_NATIVE, new bytes(0)); |
||
| 42 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 43 |
params.push(afterSettleCbParam); |
||
| 44 |
} |
||
| 45 | |||
| 46 | |||
| 47 |
function _beforeSettleNative(bytes memory preSettleParams) internal {
|
||
| 48 |
(_settleNativeActor, _settleNativeAmount) = abi.decode(preSettleParams, (address, uint256)); |
||
| 49 |
// transfer currency to actionsRouter |
||
| 50 |
payable(address(actionsRouter)).transfer(_settleNativeAmount); |
||
| 51 | |||
| 52 |
_verifyGlobalProperties(_settleNativeActor, CurrencyLibrary.NATIVE); |
||
| 53 |
} |
||
| 54 | |||
| 55 |
function _afterSettleNative(uint256 paid) internal {
|
||
| 56 |
_verifyGlobalProperties(_settleNativeActor, CurrencyLibrary.NATIVE); |
||
| 57 |
_addToActorsCredits(_settleNativeActor, CurrencyLibrary.NATIVE, paid); |
||
| 58 |
|
||
| 59 | |||
| 60 |
} |
||
| 61 | |||
| 62 | |||
| 63 |
} |
||
| 64 | |||
| 65 |
| Lines covered: | 0 / 132 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 |
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
|
||
| 19 | |||
| 20 |
contract SwapActionProps is ActionFuzzBase {
|
||
| 21 |
using PoolIdLibrary for PoolKey; |
||
| 22 |
using CurrencyLibrary for Currency; |
||
| 23 |
using StateLibrary for IPoolManager; |
||
| 24 |
using TransientStateLibrary for IPoolManager; |
||
| 25 |
using ProtocolFeeLibrary for uint16; |
||
| 26 | |||
| 27 |
bool _swapZeroForOne; |
||
| 28 |
int256 _swapAmountSpecified; |
||
| 29 |
PoolKey _swapPoolKey; |
||
| 30 |
uint160 _swapPriceLimit; |
||
| 31 |
int24 _swapTickBefore; |
||
| 32 |
uint24 _swapLpFee; |
||
| 33 |
uint24 _swapProtocolFee; |
||
| 34 |
uint160 _swapSqrtPriceX96Before; |
||
| 35 |
int256 _swapCurrencyDelta0Before; |
||
| 36 |
int256 _swapCurrencyDelta1Before; |
||
| 37 |
uint128 _swapLiquidityBefore; |
||
| 38 |
uint256 _swapFeeGrowthGlobal0X128Before; |
||
| 39 |
uint256 _swapFeeGrowthGlobal1X128Before; |
||
| 40 |
uint256 _swapProtocolFees0; |
||
| 41 |
uint256 _swapProtocolFees1; |
||
| 42 | |||
| 43 |
uint256 _swapExpectedProtocolFee; |
||
| 44 |
uint256 _swapExpectedLpFee; |
||
| 45 | |||
| 46 |
function _addSwap(bool zeroForOne, int256 amountSpecified, PoolKey memory pk, uint160 priceLimit) internal {
|
||
| 47 |
bytes memory swapParam = abi.encode(zeroForOne, amountSpecified, pk, priceLimit); |
||
| 48 | |||
| 49 |
bytes memory beforeSwapCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_SWAP, swapParam); |
||
| 50 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 51 |
params.push(beforeSwapCbParam); |
||
| 52 | |||
| 53 |
actions.push(Actions.SWAP); |
||
| 54 |
params.push(swapParam); |
||
| 55 | |||
| 56 |
bytes memory afterSwapCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SWAP, new bytes(0)); |
||
| 57 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 58 |
params.push(afterSwapCbParam); |
||
| 59 |
} |
||
| 60 | |||
| 61 |
function addSwap(uint8 poolIdx, int256 amountSpecified, bool zeroForOne) public {
|
||
| 62 |
PoolKey memory pk = _clampToValidPool(poolIdx); |
||
| 63 |
uint160 priceLimit = zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT; |
||
| 64 |
_addSwap(zeroForOne, amountSpecified, pk, priceLimit); |
||
| 65 |
} |
||
| 66 | |||
| 67 |
function _beforeSwap(bytes memory preSwapParam) internal {
|
||
| 68 |
(_swapZeroForOne, _swapAmountSpecified, _swapPoolKey, _swapPriceLimit) = abi.decode(preSwapParam, (bool, int256, PoolKey, uint160)); |
||
| 69 |
(_swapSqrtPriceX96Before, _swapTickBefore, _swapProtocolFee, _swapLpFee) = manager.getSlot0(_swapPoolKey.toId()); |
||
| 70 | |||
| 71 |
_swapCurrencyDelta0Before = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0); |
||
| 72 |
_swapCurrencyDelta1Before = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1); |
||
| 73 | |||
| 74 |
emit LogInt256("currency 0 delta before swap", _swapCurrencyDelta0Before);
|
||
| 75 |
emit LogInt256("currency 1 delta before swap", _swapCurrencyDelta1Before);
|
||
| 76 |
emit LogUint256("sqrt price of pool before swap", _swapSqrtPriceX96Before);
|
||
| 77 |
emit LogUint256("sqrt price limit", _swapPriceLimit);
|
||
| 78 | |||
| 79 |
_swapLiquidityBefore = manager.getLiquidity(_swapPoolKey.toId()); |
||
| 80 |
(_swapFeeGrowthGlobal0X128Before, _swapFeeGrowthGlobal1X128Before) = manager.getFeeGrowthGlobals(_swapPoolKey.toId()); |
||
| 81 | |||
| 82 |
_swapProtocolFees0 = manager.protocolFeesAccrued(_swapPoolKey.currency0); |
||
| 83 |
_swapProtocolFees1 = manager.protocolFeesAccrued(_swapPoolKey.currency1); |
||
| 84 |
emit LogUint256("initial protocol fees collected amount0", _swapProtocolFees0);
|
||
| 85 |
emit LogUint256("initial protocol fees collected amount1", _swapProtocolFees1);
|
||
| 86 | |||
| 87 |
(_swapExpectedProtocolFee, _swapExpectedLpFee) = _calculateExpectedLPAndProtocolFees(_swapPoolKey, _swapZeroForOne, _swapAmountSpecified, _swapPriceLimit); |
||
| 88 | |||
| 89 |
_verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency0); |
||
| 90 |
_verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency1); |
||
| 91 |
} |
||
| 92 | |||
| 93 | |||
| 94 | |||
| 95 | |||
| 96 |
function _afterSwap(BalanceDelta delta) internal {
|
||
| 97 |
emit LogInt256("amount0 balanceDelta", delta.amount0());
|
||
| 98 |
emit LogInt256("amount1 balanceDelta", delta.amount1());
|
||
| 99 | |||
| 100 |
/* Properties for the pool's slot0 and how its values have changed */ |
||
| 101 |
(uint160 newPrice, int24 newTick,,) = manager.getSlot0(_swapPoolKey.toId()); |
||
| 102 |
_verifySlot0Properties(newPrice, newTick); |
||
| 103 |
|
||
| 104 |
/* Fee properties */ |
||
| 105 |
_verifyFeeProperties(delta, newTick); |
||
| 106 | |||
| 107 | |||
| 108 |
/* Properties for what we expect has not changed */ |
||
| 109 |
uint128 newLiquidity = manager.getLiquidity(_swapPoolKey.toId()); |
||
| 110 |
if (newTick == _swapTickBefore) {
|
||
| 111 |
// UNI-SWAP-1 (hehe) |
||
| 112 |
assertEq(newLiquidity, _swapLiquidityBefore, "After a swap, if the pool's active tick did not change, its liquidity must be the same as it was before the swap."); |
||
| 113 |
} |
||
| 114 | |||
| 115 |
/* Boundary conditions of swap() */ |
||
| 116 |
_verifyBoundaryProperties(newPrice, newTick); |
||
| 117 | |||
| 118 |
/* Verify the key properties of swap() */ |
||
| 119 |
_verifySwapBehavior(delta, newPrice, newTick); |
||
| 120 | |||
| 121 |
/* Update our ledger of virtual pool reserves */ |
||
| 122 |
_updateSwapBalances(delta); |
||
| 123 | |||
| 124 |
/* These props needs to be verified at the end of the updates */ |
||
| 125 |
_verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency0); |
||
| 126 |
_verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency1); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
function _verifySlot0Properties(uint160 newPrice, int24 newTick) internal {
|
||
| 130 |
emit LogUint256("new pool price", newPrice);
|
||
| 131 |
if (_swapZeroForOne) {
|
||
| 132 |
// TODO: see if we can get this more restrictive (lte => lt), or even eq |
||
| 133 |
// UNI-SWAP-2 |
||
| 134 |
assertLte(newPrice, _swapSqrtPriceX96Before, "The pool's sqrtPriceX96 should decrease or stay the same after making a zeroForOne swap."); |
||
| 135 |
// UNI-SWAP-4 |
||
| 136 |
assertGte(newPrice, _swapPriceLimit, "The pool's new sqrtPriceX96 must not be lower than the transaction's price limit after making a zeroForOne swap."); |
||
| 137 |
// UNI-SWAP-6 |
||
| 138 |
assertLte(newTick, _swapTickBefore, "The pool's active tick should decrease or stay the same after making a zeroForOne swap."); |
||
| 139 | |||
| 140 |
if (_swapTickBefore - newTick >= 1) {
|
||
| 141 |
emit LogString("Successfully crossed multiple ticks in same tx, moving lower");
|
||
| 142 |
} else if (_swapTickBefore == newTick) {
|
||
| 143 |
emit LogString("Successfully stayed in the same tick while moving lower");
|
||
| 144 |
} |
||
| 145 |
} else {
|
||
| 146 |
// TODO: see if we can get this more restrictive (gte => gt), or even eq |
||
| 147 |
// UNI-SWAP-3 |
||
| 148 |
assertGte(newPrice, _swapSqrtPriceX96Before, "The pool's sqrtPriceX96 should increase or stay the same after making a oneForZero swap."); |
||
| 149 |
// UNI-SWAP-5 |
||
| 150 |
assertLte(newPrice, _swapPriceLimit, "The pool's new sqrtPriceX96 must not exceed the transaction's price limit after making a oneForZero swap."); |
||
| 151 |
// UNI-SWAP-7 |
||
| 152 |
assertGte(newTick, _swapTickBefore, "The pool's active tick should increase or stay the same after making a oneForZero swap."); |
||
| 153 | |||
| 154 |
if (newTick - _swapTickBefore >= 1) {
|
||
| 155 |
emit LogString("Successfully crossed multiple ticks in same tx, moving higher");
|
||
| 156 |
} else if (_swapTickBefore == newTick) {
|
||
| 157 |
emit LogString("Successfully stayed in the same tick while moving lower");
|
||
| 158 |
} |
||
| 159 |
} |
||
| 160 |
} |
||
| 161 | |||
| 162 |
function _getNumCrossedTicks(int24 oldTick, int24 newTick) internal pure returns (uint256) {
|
||
| 163 |
if (oldTick > newTick) {
|
||
| 164 |
return uint256(int256(oldTick - newTick)); |
||
| 165 |
} else {
|
||
| 166 |
return uint256(int256(newTick - oldTick)); |
||
| 167 |
} |
||
| 168 |
} |
||
| 169 | |||
| 170 |
function _verifyFeeProperties(BalanceDelta, int24) internal {
|
||
| 171 |
/* Properties for how the fees have changed */ |
||
| 172 |
(,, uint24 newProtocolFee, uint24 newLpFee) = manager.getSlot0(_swapPoolKey.toId()); |
||
| 173 |
(uint256 newSwapFeeGrowth0X128, uint256 newSwapFeeGrowth1X128) = manager.getFeeGrowthGlobals(_swapPoolKey.toId()); |
||
| 174 |
|
||
| 175 |
uint256 swapFee = newProtocolFee == 0 ? newLpFee : uint16(newProtocolFee).calculateSwapFee(newLpFee); |
||
| 176 |
emit LogUint256("swap fee", swapFee);
|
||
| 177 |
//uint256 numTicksCrossed = _getNumCrossedTicks(newTick, _swapTickBefore); |
||
| 178 | |||
| 179 |
if (_swapZeroForOne) {
|
||
| 180 |
// UNI-SWAP-8 |
||
| 181 |
assertEq(newSwapFeeGrowth1X128, _swapFeeGrowthGlobal1X128Before, "After a zeroForOne swap, the fee growth for currency1 should not change."); |
||
| 182 | |||
| 183 |
// for now, we can only validate the following props when numTicksCrossed == 0. This is because when multiple ticks are crossed, |
||
| 184 |
// we need to get the liquidity at each tick crossed and figure out how much of the tick was consumed. |
||
| 185 |
// This is totally possible, but has to be saved for future work. |
||
| 186 |
/* |
||
| 187 |
if (true) {
|
||
| 188 |
uint256 theoreticalFee = FullMath.mulDivRoundingUp(uint256(int256(-delta.amount0())), swapFee, SwapMath.MAX_FEE_PIPS); |
||
| 189 |
uint256 expectedFeeGrowthDeltaX128 = FullMath.mulDiv(theoreticalFee, FixedPoint128.Q128, _swapLiquidityBefore); |
||
| 190 |
//uint256 expectedFeeGrowth = _calculateExpectedFeeGrowth(expectedFeeGrowthDeltaX128, _swapFeeGrowthGlobal0X128Before); |
||
| 191 |
// UNI-SWAP-10 (remove) |
||
| 192 |
//assertEq(expectedFeeGrowth, newSwapFeeGrowth0X128, "After a zeroForOneSwap, the fee growth for currency0 should match the expected fee growth."); |
||
| 193 |
} |
||
| 194 |
*/ |
||
| 195 |
} else {
|
||
| 196 |
// UNI-SWAP-9 |
||
| 197 |
assertEq(newSwapFeeGrowth0X128, _swapFeeGrowthGlobal0X128Before, "After a oneForZero swap, the fee growth for currency0 should not change."); |
||
| 198 |
/* |
||
| 199 |
if (true) {
|
||
| 200 |
uint256 theoreticalFee = FullMath.mulDivRoundingUp(uint256(int256(-delta.amount1())), swapFee, SwapMath.MAX_FEE_PIPS); |
||
| 201 |
emit LogUint256("swap liquidity", _swapLiquidityBefore);
|
||
| 202 |
uint256 expectedFeeGrowthDeltaX128 = FullMath.mulDiv(theoreticalFee, FixedPoint128.Q128, _swapLiquidityBefore); |
||
| 203 |
emit LogUint256("prev fee growth", _swapFeeGrowthGlobal1X128Before);
|
||
| 204 |
emit LogUint256("theoretical fee", theoreticalFee);
|
||
| 205 |
emit LogUint256("expectedFeeGrowthDeltaX128", expectedFeeGrowthDeltaX128);
|
||
| 206 |
//uint256 expectedFeeGrowth = _calculateExpectedFeeGrowth(expectedFeeGrowthDeltaX128, _swapFeeGrowthGlobal1X128Before); |
||
| 207 |
// UNI-SWAP-11 (remove) |
||
| 208 |
//assertEq(expectedFeeGrowth, newSwapFeeGrowth1X128, "After a oneForZero, the fee growth for currency1 should match the expected fee growth. "); |
||
| 209 |
} |
||
| 210 |
*/ |
||
| 211 |
} |
||
| 212 |
} |
||
| 213 | |||
| 214 | |||
| 215 |
function _verifyBoundaryProperties(uint160 newPrice, int24 newTick) internal {
|
||
| 216 |
// UNI-SWAP-10 |
||
| 217 |
assertNeq(_swapAmountSpecified, 0, "The swap action must revert if swap amount is zero."); |
||
| 218 |
// UNI-SWAP-11 |
||
| 219 |
assertLt(newPrice, TickMath.MAX_SQRT_PRICE, "The pool's new price must be less than MAX_SQRT_PRICE"); |
||
| 220 |
// UNI-SWAP-12 |
||
| 221 |
assertGt(newPrice, TickMath.MIN_SQRT_PRICE, "The pool's new price must be greater than or equal to MIN_SQRT_PRICE"); |
||
| 222 |
// UNI-SWAP-13 |
||
| 223 |
assertLte(newTick, TickMath.MAX_TICK, "The pool's new tick must be less than or equal to MAX_TICK"); |
||
| 224 |
// UNI-SWAP-14 |
||
| 225 |
assertGte(newTick, TickMath.MIN_TICK, "The pool's new tick must be greater than or equal to MIN_TICK"); |
||
| 226 |
} |
||
| 227 | |||
| 228 |
function _verifySwapBehavior(BalanceDelta delta, uint160 newPrice, int24) internal {
|
||
| 229 |
int256 currencyDelta0After = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0); |
||
| 230 |
int256 currencyDelta1After = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1); |
||
| 231 | |||
| 232 |
/* Properties of swap()'s behavior */ |
||
| 233 |
// We use fromBalanceDelta/toBalanceDelta to reduce the number of properties. There's no need to if(zeroForOne) constantly. |
||
| 234 |
// The assumptions introduced by using this abstraction are checked in SWAP-PROP-17/SWAP-PROP-18. |
||
| 235 |
int128 fromBalanceDelta = _swapZeroForOne ? delta.amount0() : delta.amount1(); |
||
| 236 |
int128 toBalanceDelta = _swapZeroForOne ? delta.amount1() : delta.amount0(); |
||
| 237 |
int256 fromCurrencyDeltaFull; |
||
| 238 |
int256 toCurrencyDeltaFull; |
||
| 239 |
if (_swapZeroForOne) {
|
||
| 240 |
fromCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0); |
||
| 241 |
toCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1); |
||
| 242 |
emit LogString("zeroForOne");
|
||
| 243 |
}else {
|
||
| 244 |
fromCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1); |
||
| 245 |
toCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0); |
||
| 246 |
emit LogString("oneforzero");
|
||
| 247 |
} |
||
| 248 |
emit LogInt256("fromBalanceDelta", fromBalanceDelta);
|
||
| 249 |
emit LogInt256("toBalanceDelta", toBalanceDelta);
|
||
| 250 |
emit LogInt256("currencyDelta0After", currencyDelta0After);
|
||
| 251 |
emit LogInt256("currencyDelta1After", currencyDelta1After);
|
||
| 252 |
emit LogInt256("_swapAmountSpecified", _swapAmountSpecified);
|
||
| 253 | |||
| 254 |
if (fromBalanceDelta != 0 && toBalanceDelta != 0){
|
||
| 255 |
// UNI-SWAP-15 transitive; Swaps respect the sqrtPriceLimit ahead of the need to consume exactInput or exactOutput. |
||
| 256 |
if(_swapPriceLimit != newPrice){
|
||
| 257 |
if (_swapAmountSpecified < 0) {
|
||
| 258 |
// exact input |
||
| 259 |
// UNI-SWAP-16, iff the price limit was not reached |
||
| 260 |
assertEq(fromBalanceDelta, _swapAmountSpecified, "For exact input swaps where the price limit is not reached, the fromBalanceDelta must match the exact input amount."); |
||
| 261 |
} else {
|
||
| 262 |
// exact output |
||
| 263 |
// UNI-SWAP-17, iff the price limit was not reached |
||
| 264 |
assertEq(toBalanceDelta, _swapAmountSpecified, "For exact output swaps where the price limit is not reached, the toBalanceDelta must match the exact output amount."); |
||
| 265 |
} |
||
| 266 |
} else {
|
||
| 267 |
// todo: use lte/gte to ensure price limit was not exceeded |
||
| 268 |
} |
||
| 269 |
} else {
|
||
| 270 |
// One or both of the deltas being zero should be a result of rounding down to zero, but there is still a case we need to check for. |
||
| 271 |
if (fromBalanceDelta == 0) {
|
||
| 272 |
// UNI-SWAP-18 |
||
| 273 |
assertEq(toBalanceDelta, 0, "If the fromBalanceDelta of a swap is zero, the toBalanceDelta must also be zero (rounding)."); |
||
| 274 |
} |
||
| 275 |
} |
||
| 276 | |||
| 277 |
/* Properties of the system's currencyDeltas and how it compares to balanceDelta */ |
||
| 278 |
// UNI-SWAP-19 |
||
| 279 |
assertGte(toBalanceDelta, 0, "For any swap, the amount credited to the user is greater than or equal to zero."); |
||
| 280 |
// UNI-SWAP-20 |
||
| 281 |
assertLte(fromBalanceDelta, 0, "For any swap, the amount credited to the user is less than or equal to zero"); |
||
| 282 | |||
| 283 |
int256 expectedDelta0After = _swapCurrencyDelta0Before + delta.amount0(); |
||
| 284 |
int256 expectedDelta1After = _swapCurrencyDelta1Before + delta.amount1(); |
||
| 285 | |||
| 286 |
// if our deltas are bigger than the liquidity that was in the pool, this action is stealing tokens from another pool. |
||
| 287 |
if(_swapZeroForOne) {
|
||
| 288 |
// UNI-SWAP-21 |
||
| 289 |
assertLte(int256(delta.amount1()), PoolLiquidities[_swapPoolKey.toId()].amount1, "For a zeroForOne swap, the amount credited to the user must be less than or equal to the total number of tradeable tokens in the pool"); |
||
| 290 |
} else {
|
||
| 291 |
// UNI-SWAP-22 |
||
| 292 |
assertLte(int256(delta.amount0()), PoolLiquidities[_swapPoolKey.toId()].amount0, "For a oneForZero swap, the amount credited to the user must be less than or equal to the total number of tradeable tokens in the pool"); |
||
| 293 |
} |
||
| 294 | |||
| 295 |
// UNI-SWAP-23 |
||
| 296 |
assertEq(currencyDelta0After, expectedDelta0After, "After a swap, the user's currencyDelta for amount0 should match the expected delta based on BalanceDelta."); |
||
| 297 |
// UNI-SWAP-24 |
||
| 298 |
assertEq(currencyDelta1After, expectedDelta1After, "After a swap, the user's currencyDelta for amount1 should match the expected delta based on BalanceDelta."); |
||
| 299 |
} |
||
| 300 | |||
| 301 |
function _updateSwapBalances(BalanceDelta delta) internal {
|
||
| 302 |
emit LogInt256("cur0 BalanceDelta from swap", delta.amount0());
|
||
| 303 |
emit LogInt256("cur1 BalanceDelta from swap", delta.amount1());
|
||
| 304 | |||
| 305 |
int256 expectedLpFee0; |
||
| 306 |
int256 expectedLpFee1; |
||
| 307 | |||
| 308 |
if(_swapZeroForOne) {
|
||
| 309 |
expectedLpFee0 = int256(_swapExpectedLpFee); |
||
| 310 |
SingletonLPFees[_swapPoolKey.currency0] += _swapExpectedLpFee; |
||
| 311 |
emit LogUint256("new singleton LP fees (amount0)", SingletonLPFees[_swapPoolKey.currency0]);
|
||
| 312 |
} else {
|
||
| 313 |
expectedLpFee1 = int256(_swapExpectedLpFee); |
||
| 314 |
SingletonLPFees[_swapPoolKey.currency1] += _swapExpectedLpFee; |
||
| 315 |
emit LogUint256("new singleton LP fees (amount1)", SingletonLPFees[_swapPoolKey.currency1]);
|
||
| 316 |
} |
||
| 317 | |||
| 318 |
{
|
||
| 319 |
uint256 protocolFeesLevied0 = (manager.protocolFeesAccrued(_swapPoolKey.currency0)-(_swapProtocolFees0)); |
||
| 320 |
uint256 protocolFeesLevied1 = (manager.protocolFeesAccrued(_swapPoolKey.currency1)-(_swapProtocolFees1)); |
||
| 321 | |||
| 322 |
emit LogUint256("protocol fees levied amount0", protocolFeesLevied0);
|
||
| 323 |
emit LogUint256("protocol fees levied amount1", protocolFeesLevied1);
|
||
| 324 | |||
| 325 |
emit LogInt256("prev pool liquidity amount0", PoolLiquidities[_swapPoolKey.toId()].amount0);
|
||
| 326 |
emit LogInt256("prev pool liquidity amount1", PoolLiquidities[_swapPoolKey.toId()].amount1);
|
||
| 327 |
|
||
| 328 |
PoolLiquidities[_swapPoolKey.toId()].amount0 -= delta.amount0() + int256(protocolFeesLevied0) + expectedLpFee0; |
||
| 329 |
PoolLiquidities[_swapPoolKey.toId()].amount1 -= delta.amount1() + int256(protocolFeesLevied1) + expectedLpFee1; |
||
| 330 |
emit LogInt256("new pool liquidity amount0", PoolLiquidities[_swapPoolKey.toId()].amount0);
|
||
| 331 |
emit LogInt256("new pool liquidity amount1", PoolLiquidities[_swapPoolKey.toId()].amount1);
|
||
| 332 | |||
| 333 |
// Update singleton liquidity, remove the amount sent/recvd from user. |
||
| 334 |
uint256 newSingletonLiq0 = _deltaAdd(SingletonLiquidity[_swapPoolKey.currency0], -(delta.amount0())); |
||
| 335 |
uint256 newSingletonLiq1 = _deltaAdd(SingletonLiquidity[_swapPoolKey.currency1], -(delta.amount1())); |
||
| 336 | |||
| 337 |
// Update singleton liquidity, remove the amount consumed by protocol. |
||
| 338 |
newSingletonLiq0 = _deltaAdd(newSingletonLiq0, -int256(protocolFeesLevied0)); |
||
| 339 |
newSingletonLiq1 = _deltaAdd(newSingletonLiq1, -int256(protocolFeesLevied1)); |
||
| 340 | |||
| 341 |
newSingletonLiq0 = _deltaAdd(newSingletonLiq0, -int256(expectedLpFee0)); |
||
| 342 |
newSingletonLiq1 = _deltaAdd(newSingletonLiq1, -int256(expectedLpFee1)); |
||
| 343 | |||
| 344 |
SingletonLiquidity[_swapPoolKey.currency0] = newSingletonLiq0; |
||
| 345 |
SingletonLiquidity[_swapPoolKey.currency1] = newSingletonLiq1; |
||
| 346 | |||
| 347 |
_updateCurrencyDelta(address(actionsRouter), _swapPoolKey.currency0, delta.amount0()); |
||
| 348 |
_updateCurrencyDelta(address(actionsRouter), _swapPoolKey.currency1, delta.amount1()); |
||
| 349 |
} |
||
| 350 | |||
| 351 |
} |
||
| 352 | |||
| 353 | |||
| 354 |
} |
| Lines covered: | 0 / 15 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract SyncActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 |
Currency _syncCurrency; |
||
| 27 | |||
| 28 |
function addSync(uint8 curIdx) public {
|
||
| 29 |
Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)]; |
||
| 30 | |||
| 31 | |||
| 32 |
bytes memory syncParams = abi.encode(currency); |
||
| 33 |
bytes memory beforeSyncCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SYNC, syncParams); |
||
| 34 | |||
| 35 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 36 |
params.push(beforeSyncCbParams); |
||
| 37 | |||
| 38 |
actions.push(Actions.SYNC); |
||
| 39 |
params.push(syncParams); |
||
| 40 | |||
| 41 |
bytes memory afterSyncCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SYNC, new bytes(0)); |
||
| 42 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 43 |
params.push(afterSyncCbParam); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function _beforeSync(bytes memory preSyncParams) internal {
|
||
| 47 |
_syncCurrency = abi.decode(preSyncParams, (Currency)); |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function _afterSync() internal {
|
||
| 51 |
if(!(_syncCurrency == CurrencyLibrary.NATIVE)){
|
||
| 52 |
RemittanceCurrency = _syncCurrency; |
||
| 53 |
RemittanceAmount = 0; |
||
| 54 |
} |
||
| 55 | |||
| 56 |
} |
||
| 57 | |||
| 58 | |||
| 59 |
} |
||
| 60 | |||
| 61 |
| Lines covered: | 0 / 25 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
|
||
| 5 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 6 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 7 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 8 |
import {Actions} from "src/test/ActionsRouter.sol";
|
||
| 9 |
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
|
||
| 10 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 11 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 12 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 15 |
import {SwapMath} from "src/libraries/SwapMath.sol";
|
||
| 16 |
import {FullMath} from "src/libraries//FullMath.sol";
|
||
| 17 |
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
|
||
| 18 | |||
| 19 |
contract TakeActionProps is ActionFuzzBase {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using ProtocolFeeLibrary for uint16; |
||
| 25 | |||
| 26 |
Currency _takeCurrency; |
||
| 27 |
address _takeActor; |
||
| 28 | |||
| 29 |
uint256 _takeAmount; |
||
| 30 |
uint256 _takeActorBalanceBefore; |
||
| 31 |
uint256 _takeSingletonBalanceBefore; |
||
| 32 | |||
| 33 |
int256 _takeActorCurrencyDeltaBefore; |
||
| 34 | |||
| 35 |
function addTake(uint8 currency1I, uint256 amount) public {
|
||
| 36 |
Currency c1 = Currencies[clampBetween(currency1I, 0, NUMBER_CURRENCIES-1)]; |
||
| 37 | |||
| 38 |
bytes memory takeParams = abi.encode(c1, address(actionsRouter), amount); |
||
| 39 | |||
| 40 |
bytes memory beforeTakeCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_TAKE, takeParams); |
||
| 41 | |||
| 42 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 43 |
params.push(beforeTakeCbParam); |
||
| 44 | |||
| 45 |
actions.push(Actions.TAKE); |
||
| 46 |
params.push(takeParams); |
||
| 47 | |||
| 48 |
bytes memory afterTakeCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_TAKE, new bytes(0)); |
||
| 49 |
actions.push(Actions.HARNESS_CALLBACK); |
||
| 50 |
params.push(afterTakeCbParam); |
||
| 51 | |||
| 52 |
} |
||
| 53 | |||
| 54 |
function _beforeTake(bytes memory preTakeParams) internal {
|
||
| 55 |
(_takeCurrency, _takeActor, _takeAmount) = abi.decode(preTakeParams, (Currency, address, uint256)); |
||
| 56 | |||
| 57 |
_takeActorBalanceBefore = _takeCurrency.balanceOf(_takeActor); |
||
| 58 |
_takeSingletonBalanceBefore = _takeCurrency.balanceOf(address(manager)); |
||
| 59 |
_takeActorCurrencyDeltaBefore = manager.currencyDelta(_takeActor, _takeCurrency); |
||
| 60 | |||
| 61 |
// assert actor currency delta is less than or equal to the pool balance |
||
| 62 |
_verifyGlobalProperties(_takeActor, _takeCurrency); |
||
| 63 |
} |
||
| 64 | |||
| 65 |
function _afterTake() internal {
|
||
| 66 |
uint256 actorBalanceAfter = _takeCurrency.balanceOf(_takeActor); |
||
| 67 |
uint256 singletonBalanceAfter = _takeCurrency.balanceOf(address(manager)); |
||
| 68 | |||
| 69 |
int256 expectedDelta = _takeActorCurrencyDeltaBefore - int256(_takeAmount); |
||
| 70 |
int256 actualDelta = manager.currencyDelta(_takeActor, _takeCurrency); |
||
| 71 |
// UNI-TAKE-1 |
||
| 72 |
assertEq(expectedDelta, actualDelta, "After executing take(), the user's currencyDelta should be the difference between their previous delta and the amount taken"); |
||
| 73 |
// UNI-TAKE-2 |
||
| 74 |
assertEq(_takeActorBalanceBefore + _takeAmount, actorBalanceAfter, "After executing take(), the user's balance should increase by the amount taken."); |
||
| 75 |
// UNI-TAKE-3 |
||
| 76 |
assertEq(_takeSingletonBalanceBefore - _takeAmount, singletonBalanceAfter, "After executing take(), the singleton's balance should decrease by the amount taken."); |
||
| 77 | |||
| 78 |
_verifyGlobalProperties(_takeActor, _takeCurrency); |
||
| 79 |
_addToActorsDebts(address(_takeActor), _takeCurrency, _takeAmount); |
||
| 80 |
} |
||
| 81 | |||
| 82 | |||
| 83 |
} |
||
| 84 |
| Lines covered: | 0 / 34 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 5 | |||
| 6 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 7 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 8 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 9 | |||
| 10 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 11 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 12 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 13 |
import {BalanceDelta} from "src/types/BalanceDelta.sol";
|
||
| 14 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 15 |
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
|
||
| 16 | |||
| 17 |
import {PoolTestBase} from "src/test/PoolTestBase.sol";
|
||
| 18 |
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
|
||
| 19 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 20 |
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
|
||
| 21 | |||
| 22 |
import {IActor} from "./IActor.sol";
|
||
| 23 |
import {PropertiesAsserts} from "../PropertiesHelper.sol";
|
||
| 24 |
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
|
||
| 25 | |||
| 26 | |||
| 27 |
contract DonationActor is PropertiesAsserts, PoolTestBase, IActor {
|
||
| 28 |
using PoolIdLibrary for PoolKey; |
||
| 29 |
using StateLibrary for IPoolManager; |
||
| 30 |
using CurrencyLibrary for Currency; |
||
| 31 |
using Hooks for IHooks; |
||
| 32 |
using LPFeeLibrary for uint24; |
||
| 33 | |||
| 34 |
address Harness; |
||
| 35 | |||
| 36 |
constructor(IPoolManager _manager) PoolTestBase(_manager) {
|
||
| 37 |
Harness = msg.sender; |
||
| 38 |
} |
||
| 39 |
|
||
| 40 |
struct CallbackData {
|
||
| 41 |
address sender; |
||
| 42 |
PoolKey key; |
||
| 43 |
uint256 amount0; |
||
| 44 |
uint256 amount1; |
||
| 45 |
bytes hookData; |
||
| 46 |
} |
||
| 47 | |||
| 48 |
function Donate(PoolKey memory key, uint256 amount0, uint256 amount1) |
||
| 49 |
external |
||
| 50 |
payable |
||
| 51 |
returns (BalanceDelta delta) |
||
| 52 |
{
|
||
| 53 |
delta = abi.decode( |
||
| 54 |
manager.unlock(abi.encode(CallbackData(msg.sender, key, amount0, amount1, new bytes(0)))), (BalanceDelta) |
||
| 55 |
); |
||
| 56 | |||
| 57 |
uint256 ethBalance = address(this).balance; |
||
| 58 |
if (ethBalance > 0) {
|
||
| 59 |
CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance); |
||
| 60 |
} |
||
| 61 |
} |
||
| 62 | |||
| 63 | |||
| 64 | |||
| 65 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 66 |
require(msg.sender == address(manager)); |
||
| 67 | |||
| 68 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 69 | |||
| 70 |
(,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 71 |
(,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 72 | |||
| 73 |
require(deltaBefore0 == 0, "deltaBefore0 is not 0"); |
||
| 74 |
require(deltaBefore1 == 0, "deltaBefore1 is not 0"); |
||
| 75 | |||
| 76 |
BalanceDelta delta = manager.donate(data.key, data.amount0, data.amount1, data.hookData); |
||
| 77 | |||
| 78 |
(,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 79 |
(,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 80 | |||
| 81 |
require(deltaAfter0 == -int256(data.amount0), "deltaAfter0 is not equal to -int256(data.amount0)"); |
||
| 82 |
require(deltaAfter1 == -int256(data.amount1), "deltaAfter1 is not equal to -int256(data.amount1)"); |
||
| 83 | |||
| 84 | |||
| 85 |
if (deltaAfter0 < 0) {
|
||
| 86 |
// obtain tokens from harness |
||
| 87 |
MockERC20(Currency.unwrap(data.key.currency0)).transferFrom(Harness, address(this), uint256(-deltaAfter0)); |
||
| 88 |
CurrencySettler.settle(data.key.currency0, manager, data.sender, uint256(-deltaAfter0), false); |
||
| 89 |
} |
||
| 90 |
if (deltaAfter1 < 0){
|
||
| 91 |
// obtain tokens from harness |
||
| 92 |
MockERC20(Currency.unwrap(data.key.currency1)).transferFrom(Harness, address(this), uint256(-deltaAfter1)); |
||
| 93 |
CurrencySettler.settle(data.key.currency1, manager, data.sender, uint256(-deltaAfter1), false); |
||
| 94 |
} |
||
| 95 |
if (deltaAfter0 > 0) {
|
||
| 96 |
// unhittable? |
||
| 97 |
assert(false); |
||
| 98 |
CurrencySettler.take(data.key.currency0, manager, data.sender, uint256(deltaAfter0), false); |
||
| 99 |
// send tokens back to harness |
||
| 100 |
data.key.currency0.transfer(Harness, uint256(deltaAfter0)); |
||
| 101 |
} |
||
| 102 |
if (deltaAfter1 > 0){
|
||
| 103 |
// unhittable? |
||
| 104 |
assert(false); |
||
| 105 |
CurrencySettler.take(data.key.currency1, manager, data.sender, uint256(deltaAfter1), false); |
||
| 106 |
// send tokens back to harness |
||
| 107 |
data.key.currency1.transfer( Harness, uint256(deltaAfter1)); |
||
| 108 |
} |
||
| 109 | |||
| 110 |
return abi.encode(delta); |
||
| 111 |
} |
||
| 112 | |||
| 113 |
function proxyApprove(Currency token, address spender) public {
|
||
| 114 |
MockERC20(Currency.unwrap(token)).approve(spender, type(uint256).max); |
||
| 115 |
} |
||
| 116 | |||
| 117 |
} |
| Lines covered: | 0 / 141 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 5 | |||
| 6 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 7 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 8 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 9 | |||
| 10 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 11 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 12 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 13 |
import {BalanceDelta} from "src/types/BalanceDelta.sol";
|
||
| 14 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 15 |
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
|
||
| 16 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 17 | |||
| 18 |
import {PoolTestBase} from "src/test/PoolTestBase.sol";
|
||
| 19 |
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
|
||
| 20 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 21 |
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
|
||
| 22 | |||
| 23 |
import {IActor} from "./IActor.sol";
|
||
| 24 |
import {PropertiesAsserts} from "../PropertiesHelper.sol";
|
||
| 25 |
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
|
||
| 26 | |||
| 27 |
import {SwapActor} from "./SwapActor.sol";
|
||
| 28 |
import {LiquidityActor} from "./LiquidityActor.sol";
|
||
| 29 |
import {DonationActor} from "./DonationActor.sol";
|
||
| 30 | |||
| 31 | |||
| 32 |
contract EndToEnd is PropertiesAsserts, Deployers {
|
||
| 33 |
using PoolIdLibrary for PoolKey; |
||
| 34 |
using CurrencyLibrary for Currency; |
||
| 35 | |||
| 36 |
PoolKey[] DeployedPools; |
||
| 37 |
mapping(PoolId => bool) PoolInitialized; |
||
| 38 |
Currency[] Currencies; |
||
| 39 | |||
| 40 | |||
| 41 |
// actors |
||
| 42 |
LiquidityActor[] LiquidityActors; |
||
| 43 |
DonationActor[] DonationActors; |
||
| 44 |
SwapActor[] SwapActors; |
||
| 45 | |||
| 46 | |||
| 47 |
uint NUMBER_CURRENCIES = 2; |
||
| 48 |
uint NUMBER_LIQUIDITY_ACTORS = 1; |
||
| 49 |
uint NUMBER_DONATION_ACTORS = 1; |
||
| 50 |
uint NUMBER_SWAP_ACTORS = 1; |
||
| 51 | |||
| 52 |
constructor () payable {
|
||
| 53 |
Deployers.deployFreshManagerAndRouters(); |
||
| 54 | |||
| 55 |
// Initialize currencies |
||
| 56 |
for (uint i = 0; i < NUMBER_CURRENCIES; i++) {
|
||
| 57 |
Currencies.push(deployMintAndApproveCurrency()); |
||
| 58 |
} |
||
| 59 | |||
| 60 |
for (uint i = 0; i < NUMBER_LIQUIDITY_ACTORS; i++) {
|
||
| 61 |
LiquidityActor a = new LiquidityActor(manager); |
||
| 62 |
LiquidityActors.push(a); |
||
| 63 |
_setupActorApprovals(a); |
||
| 64 |
} |
||
| 65 | |||
| 66 |
for (uint i = 0; i < NUMBER_DONATION_ACTORS; i++) {
|
||
| 67 |
DonationActor a = new DonationActor(manager); |
||
| 68 |
DonationActors.push(a); |
||
| 69 |
_setupActorApprovals(a); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
for (uint i = 0; i < NUMBER_SWAP_ACTORS; i++) {
|
||
| 73 |
SwapActor a = new SwapActor(manager); |
||
| 74 |
SwapActors.push(a); |
||
| 75 |
_setupActorApprovals(a); |
||
| 76 |
} |
||
| 77 |
} |
||
| 78 | |||
| 79 |
function _setupActorApprovals(IActor c) internal {
|
||
| 80 |
address[9] memory toApprove = [ |
||
| 81 |
address(swapRouter), |
||
| 82 |
address(swapRouterNoChecks), |
||
| 83 |
address(modifyLiquidityRouter), |
||
| 84 |
address(modifyLiquidityNoChecks), |
||
| 85 |
address(donateRouter), |
||
| 86 |
address(takeRouter), |
||
| 87 |
address(claimsRouter), |
||
| 88 |
address(nestedActionRouter.executor()), |
||
| 89 |
address(actionsRouter) |
||
| 90 |
]; |
||
| 91 | |||
| 92 |
for(uint i = 0; i < NUMBER_CURRENCIES; i++) {
|
||
| 93 |
Currency cur = Currencies[i]; |
||
| 94 |
// By giving actors approval to this contracts funds, we allow them to search the full totalSupply space. |
||
| 95 |
// If we distributed tokens to each actor, they would be limited to exploration using tokens up to |
||
| 96 |
// totalSupply/numActors. |
||
| 97 |
MockERC20(Currency.unwrap(cur)).approve(address(c), type(uint256).max); |
||
| 98 | |||
| 99 |
for( uint approveI=0; approveI< toApprove.length; approveI++) {
|
||
| 100 |
c.proxyApprove(cur, toApprove[approveI]); |
||
| 101 |
} |
||
| 102 |
} |
||
| 103 |
} |
||
| 104 | |||
| 105 |
function _clampLiquidityActor(uint8 actorIndex) internal returns (LiquidityActor) {
|
||
| 106 |
actorIndex = uint8(clampBetween(actorIndex, 0, NUMBER_LIQUIDITY_ACTORS-1)); |
||
| 107 |
emit LogUint256("LiquidityActor index", actorIndex);
|
||
| 108 |
return LiquidityActors[actorIndex]; |
||
| 109 |
} |
||
| 110 | |||
| 111 |
function _clampDonationActor(uint8 actorIndex) internal returns (DonationActor) {
|
||
| 112 |
actorIndex = uint8(clampBetween(actorIndex, 0, NUMBER_DONATION_ACTORS-1)); |
||
| 113 |
emit LogUint256("DonationActor index", actorIndex);
|
||
| 114 |
return DonationActors[actorIndex]; |
||
| 115 |
} |
||
| 116 |
function _clampSwapActor(uint8 actorIndex) internal returns (SwapActor) {
|
||
| 117 |
actorIndex = uint8(clampBetween(actorIndex, 0, NUMBER_SWAP_ACTORS-1)); |
||
| 118 |
emit LogUint256("SwapActor index", actorIndex);
|
||
| 119 |
return SwapActors[actorIndex]; |
||
| 120 |
} |
||
| 121 | |||
| 122 |
function _clampToValidCurrencies(uint8 currency1I, uint8 currency2I) internal returns (Currency, Currency) {
|
||
| 123 |
uint c1 = clampBetween(currency1I, 0, NUMBER_CURRENCIES-1); |
||
| 124 |
uint c2 = clampBetween(currency2I, 0, NUMBER_CURRENCIES-1); |
||
| 125 |
require(c1 != c2); |
||
| 126 | |||
| 127 |
Currency cur1 = Currencies[c1]; |
||
| 128 |
Currency cur2 = Currencies[c2]; |
||
| 129 |
if (cur1 >= cur2) {
|
||
| 130 |
emit LogAddress("address 1", address(Currency.unwrap(cur2)));
|
||
| 131 |
emit LogAddress("address 2", address(Currency.unwrap(cur1)));
|
||
| 132 |
return (cur2, cur1); |
||
| 133 |
} else {
|
||
| 134 |
emit LogAddress("address 1", address(Currency.unwrap(cur1)));
|
||
| 135 |
emit LogAddress("address 2", address(Currency.unwrap(cur2)));
|
||
| 136 |
return (cur1, cur2); |
||
| 137 |
} |
||
| 138 |
} |
||
| 139 | |||
| 140 |
function _clampToValidPool(uint poolIndex) internal returns ( PoolKey memory) {
|
||
| 141 |
poolIndex = clampBetween(poolIndex, 0, DeployedPools.length-1); |
||
| 142 |
emit LogUint256("Pool index", poolIndex);
|
||
| 143 |
return DeployedPools[poolIndex]; |
||
| 144 |
} |
||
| 145 | |||
| 146 |
function _clampToUsableTicks(int24 minTick, int24 maxTick, PoolKey memory poolKey) internal returns (int24, int24) {
|
||
| 147 |
int24 minUsableTick = TickMath.minUsableTick(poolKey.tickSpacing); |
||
| 148 |
int24 maxUsableTick = TickMath.maxUsableTick(poolKey.tickSpacing); |
||
| 149 | |||
| 150 |
emit LogInt256("minUsableTick", minUsableTick);
|
||
| 151 |
emit LogInt256("maxUsableTick", maxUsableTick);
|
||
| 152 | |||
| 153 |
minTick = int24(clampBetween(minTick, minUsableTick, maxUsableTick)); |
||
| 154 |
maxTick = int24(clampBetween(maxTick, minUsableTick, maxUsableTick)); |
||
| 155 | |||
| 156 |
if (maxTick < minTick) {
|
||
| 157 |
int24 tmp = minTick; |
||
| 158 |
minTick = maxTick; |
||
| 159 |
maxTick = tmp; |
||
| 160 |
} |
||
| 161 | |||
| 162 |
emit LogInt256("minTick", minTick);
|
||
| 163 |
emit LogInt256("maxTick", maxTick);
|
||
| 164 |
return (minTick, maxTick); |
||
| 165 |
} |
||
| 166 | |||
| 167 |
/// @custom:notes This works the same way as e2e_createPool, but clamps inputs to correct values to help our coverage. |
||
| 168 |
function e2e_CreatePool_Coverage(uint8 currency1I, uint8 currency2I, int16 tickSpacing, uint256 startPrice, uint256 fee) public {
|
||
| 169 |
Currency c1; |
||
| 170 |
Currency c2; |
||
| 171 |
(c1, c2) = _clampToValidCurrencies(currency1I, currency2I); |
||
| 172 |
int24 tickSpacingClamped = int24(clampBetween(tickSpacing,1, type(int16).max)); |
||
| 173 |
emit LogInt256("tickSpacingClamped", tickSpacingClamped);
|
||
| 174 | |||
| 175 |
uint256 initialPrice = clampBetween(startPrice, 4295128739, 1461446703485210103287273052203988822378723970342-1); |
||
| 176 |
emit LogUint256("initialPrice", initialPrice);
|
||
| 177 |
|
||
| 178 |
uint256 initialFee = clampBetween(fee, 0, 1_000_000); |
||
| 179 |
emit LogUint256("initialFee", fee);
|
||
| 180 | |||
| 181 |
PoolKey memory k = PoolKey(c1, c2, uint24(initialFee), tickSpacingClamped, IHooks(address(0))); |
||
| 182 |
PoolId id = k.toId(); |
||
| 183 |
if (PoolInitialized[id]){
|
||
| 184 |
return; |
||
| 185 |
} |
||
| 186 | |||
| 187 |
int24 tick; |
||
| 188 |
try manager.initialize(k, uint160(initialPrice), ZERO_BYTES) returns (int24 t) {
|
||
| 189 |
tick = t; |
||
| 190 |
} |
||
| 191 |
catch {
|
||
| 192 |
// todo: REVISIT |
||
| 193 |
// assertWithMsg(false, "manager.initialize() threw an unknown exception. investigate"); |
||
| 194 | |||
| 195 |
return; |
||
| 196 |
} |
||
| 197 |
|
||
| 198 |
DeployedPools.push(k); |
||
| 199 |
PoolInitialized[id] = true; |
||
| 200 | |||
| 201 |
e2e_ProvideLiquidityFullRange(0, 0, 1 ether); |
||
| 202 |
} |
||
| 203 | |||
| 204 | |||
| 205 |
/// @custom:notes This function facilitates the creation of new pools for other properties. |
||
| 206 |
function e2e_CreatePool(uint8 currency1I, uint8 currency2I, int16 tickSpacing, uint256 startPrice, uint256 fee) public {
|
||
| 207 |
Currency c1; |
||
| 208 |
Currency c2; |
||
| 209 |
(c1, c2) = _clampToValidCurrencies(currency1I, currency2I); |
||
| 210 |
int24 tickSpacingClamped = int24(clampBetween(tickSpacing,1, type(int16).max)); |
||
| 211 |
emit LogInt256("tickSpacingClamped", tickSpacingClamped);
|
||
| 212 | |||
| 213 |
uint256 initialPrice = startPrice; |
||
| 214 |
emit LogUint256("initialPrice", initialPrice);
|
||
| 215 |
emit LogUint256("initialFee", fee);
|
||
| 216 | |||
| 217 |
PoolKey memory k = PoolKey(c1, c2, uint24(fee), tickSpacingClamped, IHooks(address(0))); |
||
| 218 |
PoolId id = k.toId(); |
||
| 219 |
bool poolinitialized = PoolInitialized[id]; |
||
| 220 | |||
| 221 |
int24 tick; |
||
| 222 |
try manager.initialize(k, uint160(initialPrice), ZERO_BYTES) returns (int24 t) {
|
||
| 223 |
tick = t; |
||
| 224 |
} |
||
| 225 |
catch (bytes memory data) {
|
||
| 226 |
if (bytes4(data) == bytes4(keccak256(bytes("PoolAlreadyInitialized()")) )){
|
||
| 227 |
// allowable exception iff poolInitialized |
||
| 228 |
assertWithMsg(poolinitialized, "initialize() reverted with PoolAlreadyInitialized() but pool is not initialized"); |
||
| 229 |
return; |
||
| 230 |
} |
||
| 231 |
if (bytes4(data) == bytes4(keccak256(bytes("InvalidSqrtPrice(uint160)")) )){
|
||
| 232 |
// allowable exception iff initialPrice is outside the valid range |
||
| 233 |
assertWithMsg(initialPrice < 4295128739 || initialPrice > 1461446703485210103287273052203988822378723970342-1, "initialize() reverted with InvalidSqrtPrice() but initialPrice is within valid range"); |
||
| 234 |
return; |
||
| 235 |
} |
||
| 236 |
if (bytes4(data) == bytes4(keccak256(bytes("LPFeeTooLarge(uint24)")) )){
|
||
| 237 |
// allowable exception iff fee is larger than 1_000_000 |
||
| 238 |
assertGt(fee, 1_000_000, "initialize() reverted with LPFeeTooLarge() but initialFee is within valid range"); |
||
| 239 |
return; |
||
| 240 |
} |
||
| 241 |
// assertWithMsg(false, "manager.initialize() threw an unknown exception. investigate"); |
||
| 242 |
return; |
||
| 243 |
} |
||
| 244 |
// we should have reverted if pool was initialized |
||
| 245 |
assertWithMsg(!poolinitialized, "initialize() did not revert, but pool is not initialized"); |
||
| 246 | |||
| 247 |
// verify tick is valid |
||
| 248 |
emit LogInt256("tick", tick);
|
||
| 249 |
assertGte(tick, TickMath.MIN_TICK, "tick below valid range"); |
||
| 250 |
assertLte(tick, TickMath.MAX_TICK, "tick above valid range"); |
||
| 251 | |||
| 252 |
// todo: alternate property about tick width? |
||
| 253 |
|
||
| 254 |
DeployedPools.push(k); |
||
| 255 |
PoolInitialized[id] = true; |
||
| 256 | |||
| 257 |
e2e_ProvideLiquidityFullRange(0, 0, 1 ether); |
||
| 258 |
} |
||
| 259 | |||
| 260 |
function e2e_DonateToLiquidity(uint8 actorIndex, uint poolIndex, uint256 amount0, uint256 amount1) public {
|
||
| 261 |
DonationActor actor = _clampDonationActor(actorIndex); |
||
| 262 |
PoolKey memory poolKey = _clampToValidPool(poolIndex); |
||
| 263 |
actor.Donate(poolKey, amount0, amount1); |
||
| 264 |
} |
||
| 265 | |||
| 266 | |||
| 267 |
function e2e_ProvideLiquidity(uint8 actorIndex, uint poolIndex, int24 minTick, int24 maxTick, int256 liquidityDelta) public {
|
||
| 268 |
LiquidityActor actor = _clampLiquidityActor(actorIndex); |
||
| 269 |
PoolKey memory poolKey = _clampToValidPool(poolIndex); |
||
| 270 | |||
| 271 |
(minTick, maxTick) = _clampToUsableTicks(minTick, maxTick, poolKey); |
||
| 272 |
actor.ProvideLiquidity(poolKey, minTick, maxTick, liquidityDelta); |
||
| 273 |
} |
||
| 274 | |||
| 275 |
/// @custom:property delta0 and delta1 must be greater than zero when providing LP for full-range liquidity |
||
| 276 |
/// @custom:precondition Pools Created (e2e_CreatePool) |
||
| 277 |
function e2e_ProvideLiquidityFullRange(uint8 actorIndex, uint poolIndex, int256 liquidityDelta) public {
|
||
| 278 |
LiquidityActor actor = _clampLiquidityActor(actorIndex); |
||
| 279 |
PoolKey memory poolKey = _clampToValidPool(poolIndex); |
||
| 280 |
int24 minTick = TickMath.minUsableTick(poolKey.tickSpacing); |
||
| 281 |
int24 maxTick = TickMath.maxUsableTick(poolKey.tickSpacing); |
||
| 282 | |||
| 283 |
uint256 delta0; |
||
| 284 |
uint256 delta1; |
||
| 285 |
(delta0, delta1) = actor.ProvideLiquidity(poolKey, minTick, maxTick, liquidityDelta); |
||
| 286 | |||
| 287 |
} |
||
| 288 | |||
| 289 |
function e2e_SwapOneDirection(uint8 actorIndex, uint poolIndex, int256 amountSpecified, bool zeroForOne) public {
|
||
| 290 |
SwapActor actor = _clampSwapActor(actorIndex); |
||
| 291 |
PoolKey memory poolKey = _clampToValidPool(poolIndex); |
||
| 292 | |||
| 293 |
actor.swapOneDirection(zeroForOne, amountSpecified, poolKey); |
||
| 294 |
} |
||
| 295 | |||
| 296 |
function e2e_SwapBidirectional(uint8 actorIndex, uint poolIndex, int256 amountSpecified, bool zeroForOne) public {
|
||
| 297 |
SwapActor actor = _clampSwapActor(actorIndex); |
||
| 298 |
PoolKey memory poolKey = _clampToValidPool(poolIndex); |
||
| 299 | |||
| 300 |
actor.swapBiDirectional(zeroForOne, amountSpecified, poolKey); |
||
| 301 |
} |
||
| 302 |
} |
| Lines covered: | 0 / 80 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 5 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 6 | |||
| 7 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 8 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 9 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 10 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 11 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 12 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 13 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 14 | |||
| 15 |
import {PropertiesAsserts} from "../PropertiesHelper.sol";
|
||
| 16 |
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
|
||
| 17 | |||
| 18 | |||
| 19 |
contract Harness is Deployers, PropertiesAsserts {
|
||
| 20 |
using PoolIdLibrary for PoolKey; |
||
| 21 |
using CurrencyLibrary for Currency; |
||
| 22 |
using StateLibrary for IPoolManager; |
||
| 23 |
using SwapInfoLibrary for SwapInfo; |
||
| 24 | |||
| 25 |
uint256 constant MAX_CURRENCIES = 5; |
||
| 26 | |||
| 27 |
PoolId poolId; |
||
| 28 | |||
| 29 |
constructor() payable {
|
||
| 30 |
Deployers.deployFreshManagerAndRouters(); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
|
||
| 34 | |||
| 35 |
function prop_CreatePool(int16 tickSpacing, uint256 startPrice, uint256 fee) public {
|
||
| 36 |
if (address(Currency.unwrap(currency0)) != address(0)) {
|
||
| 37 |
return; |
||
| 38 |
} |
||
| 39 | |||
| 40 |
int24 tickSpacingClamped = int24(clampBetween(tickSpacing,1, type(int16).max)); |
||
| 41 |
uint256 initialPrice = clampBetween(startPrice, TickMath.MIN_SQRT_PRICE,TickMath.MAX_SQRT_PRICE); |
||
| 42 |
uint256 initialFee = clampBetween(fee, 0, 1_000_000); |
||
| 43 | |||
| 44 |
Deployers.deployMintAndApprove2Currencies(); |
||
| 45 |
key = PoolKey(currency0, currency1, uint24(initialFee), tickSpacingClamped, IHooks(address(0))); |
||
| 46 |
poolId = key.toId(); |
||
| 47 |
manager.initialize(key, uint160(initialPrice), ZERO_BYTES); |
||
| 48 | |||
| 49 |
modifyLiquidityRouter.modifyLiquidity( |
||
| 50 |
key, |
||
| 51 |
IPoolManager.ModifyLiquidityParams( |
||
| 52 |
TickMath.minUsableTick(tickSpacingClamped), |
||
| 53 |
TickMath.maxUsableTick(tickSpacingClamped), 10_000 ether, 0), |
||
| 54 |
ZERO_BYTES |
||
| 55 |
); |
||
| 56 | |||
| 57 |
// make sure the corpus contains some more extreme conditions |
||
| 58 |
uint leeway = 10; |
||
| 59 |
if (int256(tickSpacingClamped) < int256(leeway)) {
|
||
| 60 |
emit LogInt256("tickSpacingClamped", tickSpacingClamped);
|
||
| 61 |
} else if (int256(tickSpacingClamped) > int256(type(uint16).max - leeway)) {
|
||
| 62 |
emit LogInt256("tickSpacingClamped", tickSpacingClamped);
|
||
| 63 |
} else {
|
||
| 64 |
emit LogInt256("tickSpacingClamped", tickSpacingClamped);
|
||
| 65 |
} |
||
| 66 | |||
| 67 |
if (initialPrice < TickMath.MIN_SQRT_PRICE + leeway) {
|
||
| 68 |
emit LogUint256("initialPrice", initialPrice);
|
||
| 69 |
} else if (initialPrice > TickMath.MAX_SQRT_PRICE - leeway) {
|
||
| 70 |
emit LogUint256("initialPrice", initialPrice);
|
||
| 71 |
} else {
|
||
| 72 |
emit LogUint256("initialPrice", initialPrice);
|
||
| 73 |
} |
||
| 74 | |||
| 75 |
if (initialFee < leeway) {
|
||
| 76 |
emit LogUint256("initialFee", initialFee);
|
||
| 77 |
} else if (initialFee > 1_000_000 - leeway) {
|
||
| 78 |
emit LogUint256("initialFee", initialFee);
|
||
| 79 |
} else {
|
||
| 80 |
emit LogUint256("initialFee", initialFee);
|
||
| 81 |
} |
||
| 82 |
} |
||
| 83 | |||
| 84 |
// Swap into and out of a pair. ensure you're left with less tokens than you started with. |
||
| 85 |
// When swapping out of the pair, this function requests all the tokens it swapped in to be swapped back out. |
||
| 86 |
function prop_BiDirectionalPathExactInput(bool zeroForOne, int256 amount) public {
|
||
| 87 |
if (address(Currency.unwrap(currency0)) == address(0)) {
|
||
| 88 |
return; |
||
| 89 |
} |
||
| 90 |
Currency fromCurrency = zeroForOne ? currency0 : currency1; |
||
| 91 |
Currency toCurrency = zeroForOne ? currency1 : currency0; |
||
| 92 | |||
| 93 |
SwapInfo memory swap1Results = SwapInfoLibrary.initialize(fromCurrency, toCurrency, address(this)); |
||
| 94 |
|
||
| 95 |
swap(key, zeroForOne, amount, ZERO_BYTES); |
||
| 96 | |||
| 97 |
swap1Results.captureSwapResults(); |
||
| 98 | |||
| 99 |
emit LogInt256("Swap 1 amount", amount);
|
||
| 100 |
emit LogInt256("Swap 1 fromDelta", swap1Results.fromDelta);
|
||
| 101 |
emit LogInt256("Swap 1 toDelta", swap1Results.toDelta);
|
||
| 102 | |||
| 103 |
assert(swap1Results.fromDelta <= 0); |
||
| 104 |
assert(swap1Results.toDelta >= 0); |
||
| 105 | |||
| 106 |
// now swap in the opposite direction using the exact amount we received |
||
| 107 |
int256 newAmount = -1 * swap1Results.toDelta; |
||
| 108 |
SwapInfo memory swap2Results = SwapInfoLibrary.initialize(toCurrency, fromCurrency, address(this)); |
||
| 109 |
swap(key, !zeroForOne, newAmount, ZERO_BYTES); |
||
| 110 |
swap2Results.captureSwapResults(); |
||
| 111 | |||
| 112 |
emit LogInt256("Swap 2 amount", newAmount);
|
||
| 113 |
emit LogInt256("Swap 2 fromDelta", swap2Results.fromDelta);
|
||
| 114 |
emit LogInt256("Swap 2 toDelta", swap2Results.toDelta);
|
||
| 115 | |||
| 116 |
assert(swap2Results.fromDelta <= 0); |
||
| 117 |
assert(swap2Results.toDelta >= 0); |
||
| 118 | |||
| 119 |
// now actually verify the property |
||
| 120 |
int256 fromBalanceDifference = swap2Results.toBalanceAfter - swap1Results.fromBalanceBefore; |
||
| 121 |
int256 toBalanceDifference = swap2Results.fromBalanceAfter - swap1Results.toBalanceBefore; |
||
| 122 |
emit LogInt256("fromBalanceDifference", fromBalanceDifference);
|
||
| 123 |
emit LogInt256("toBalanceDifference", toBalanceDifference);
|
||
| 124 |
assertLt(fromBalanceDifference, 0, "Must not have more tokens than started with (from)"); |
||
| 125 |
// re-add this if using a static newAmount |
||
| 126 |
assertLte(toBalanceDifference, 0, "Must not have more tokens than started with (to)"); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
// Swap into and out of a pair. ensure you're left with less tokens than you started with. |
||
| 130 |
function prop_BidirectionalPath(bool zeroForOne, int256 amount, uint128 reverseAmount) public {
|
||
| 131 |
if (address(Currency.unwrap(currency0)) == address(0)) {
|
||
| 132 |
return; |
||
| 133 |
} |
||
| 134 |
Currency fromCurrency = zeroForOne ? currency0 : currency1; |
||
| 135 |
Currency toCurrency = zeroForOne ? currency1 : currency0; |
||
| 136 | |||
| 137 |
SwapInfo memory swap1Results = SwapInfoLibrary.initialize(fromCurrency, toCurrency, address(this)); |
||
| 138 |
|
||
| 139 |
swap(key, zeroForOne, amount, ZERO_BYTES); |
||
| 140 | |||
| 141 |
swap1Results.captureSwapResults(); |
||
| 142 | |||
| 143 |
emit LogInt256("Swap 1 amount", amount);
|
||
| 144 |
emit LogInt256("Swap 1 fromDelta", swap1Results.fromDelta);
|
||
| 145 |
emit LogInt256("Swap 1 toDelta", swap1Results.toDelta);
|
||
| 146 | |||
| 147 |
assert(swap1Results.fromDelta <= 0); |
||
| 148 |
assert(swap1Results.toDelta >= 0); |
||
| 149 | |||
| 150 |
// now swap in the opposite direction using exact input between 1 and the original swapped amount. |
||
| 151 |
int256 newAmount = -1 * int256(clampBetween(reverseAmount, 1, uint256(swap1Results.toDelta))); |
||
| 152 |
SwapInfo memory swap2Results = SwapInfoLibrary.initialize(toCurrency, fromCurrency, address(this)); |
||
| 153 |
swap(key, !zeroForOne, newAmount, ZERO_BYTES); |
||
| 154 |
swap2Results.captureSwapResults(); |
||
| 155 | |||
| 156 |
emit LogInt256("Swap 2 amount", newAmount);
|
||
| 157 |
emit LogInt256("Swap 2 fromDelta", swap2Results.fromDelta);
|
||
| 158 |
emit LogInt256("Swap 2 toDelta", swap2Results.toDelta);
|
||
| 159 | |||
| 160 |
assert(swap2Results.fromDelta <= 0); |
||
| 161 |
assert(swap2Results.toDelta >= 0); |
||
| 162 | |||
| 163 |
// now actually verify the property |
||
| 164 |
int256 fromBalanceDifference = swap2Results.toBalanceAfter - swap1Results.fromBalanceBefore; |
||
| 165 |
int256 toBalanceDifference = swap2Results.fromBalanceAfter - swap1Results.toBalanceBefore; |
||
| 166 |
emit LogInt256("fromBalanceDifference", fromBalanceDifference);
|
||
| 167 |
emit LogInt256("toBalanceDifference", toBalanceDifference);
|
||
| 168 |
assertLt(fromBalanceDifference, 0, "Must not have more tokens than started with (from)"); |
||
| 169 |
} |
||
| 170 |
} |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import {Currency, CurrencyLibrary} from "src/types/Currency.sol";
|
||
| 5 | |||
| 6 |
interface IActor{
|
||
| 7 |
function proxyApprove(Currency token, address spender) external; |
||
| 8 |
} |
| Lines covered: | 0 / 15 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 5 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 6 | |||
| 7 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 8 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 9 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 10 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 11 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 12 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 13 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 14 | |||
| 15 |
import {PropertiesAsserts} from "../PropertiesHelper.sol";
|
||
| 16 | |||
| 17 | |||
| 18 |
struct SwapInfo {
|
||
| 19 |
Currency fromCurrency; |
||
| 20 |
Currency toCurrency; |
||
| 21 |
address User; |
||
| 22 |
int256 fromBalanceBefore; |
||
| 23 |
int256 toBalanceBefore; |
||
| 24 |
int256 fromBalanceAfter; |
||
| 25 |
int256 toBalanceAfter; |
||
| 26 |
int256 fromDelta; |
||
| 27 |
int256 toDelta; |
||
| 28 |
} |
||
| 29 | |||
| 30 |
library SwapInfoLibrary {
|
||
| 31 |
function initialize(Currency fromCurrency, Currency toCurrency, address user) internal view returns (SwapInfo memory) {
|
||
| 32 |
return SwapInfo({
|
||
| 33 |
User: user, |
||
| 34 |
fromCurrency: fromCurrency, |
||
| 35 |
toCurrency: toCurrency, |
||
| 36 |
fromBalanceBefore: int256(fromCurrency.balanceOf(user)), |
||
| 37 |
toBalanceBefore: int256(toCurrency.balanceOf(user)), |
||
| 38 |
fromBalanceAfter: 0, |
||
| 39 |
toBalanceAfter: 0, |
||
| 40 |
fromDelta: 0, |
||
| 41 |
toDelta: 0 |
||
| 42 |
}); |
||
| 43 |
} |
||
| 44 | |||
| 45 |
function captureSwapResults(SwapInfo memory s) internal view {
|
||
| 46 |
s.fromBalanceAfter = int256(s.fromCurrency.balanceOf(s.User)); |
||
| 47 |
s.toBalanceAfter = int256(s.toCurrency.balanceOf(s.User)); |
||
| 48 |
s.fromDelta = int256(s.fromBalanceAfter) - int256(s.fromBalanceBefore); |
||
| 49 |
s.toDelta = int256(s.toBalanceAfter) - int256(s.toBalanceBefore); |
||
| 50 |
} |
||
| 51 |
} |
||
| 52 |
using SwapInfoLibrary for SwapInfo global; |
||
| 53 |
| Lines covered: | 0 / 61 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 5 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 6 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 7 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 8 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 9 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 10 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 11 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 12 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 13 |
import {PropertiesAsserts} from "../PropertiesHelper.sol";
|
||
| 14 |
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
|
||
| 15 |
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
|
||
| 16 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 17 |
import {IActor} from "./IActor.sol";
|
||
| 18 |
import {BalanceDelta} from "src/types/BalanceDelta.sol";
|
||
| 19 |
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
|
||
| 20 |
import {PoolTestBase} from "src/test/PoolTestBase.sol";
|
||
| 21 |
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
|
||
| 22 | |||
| 23 |
contract LiquidityActor is PropertiesAsserts, PoolTestBase, IActor {
|
||
| 24 |
using PoolIdLibrary for PoolKey; |
||
| 25 |
using StateLibrary for IPoolManager; |
||
| 26 |
using CurrencyLibrary for Currency; |
||
| 27 |
using Hooks for IHooks; |
||
| 28 |
using LPFeeLibrary for uint24; |
||
| 29 | |||
| 30 |
struct LpPosition {
|
||
| 31 |
PoolKey poolKey; |
||
| 32 |
int24 minTick; |
||
| 33 |
int24 maxTick; |
||
| 34 |
uint256 liquidity; |
||
| 35 |
bytes32 salt; |
||
| 36 |
} |
||
| 37 | |||
| 38 |
mapping(PoolId => mapping(uint256 => LpPosition)) lpPositions; |
||
| 39 |
mapping(PoolId => uint256) lpPositionCount; |
||
| 40 |
address Harness; |
||
| 41 |
|
||
| 42 |
constructor(IPoolManager _manager) PoolTestBase(_manager) {
|
||
| 43 |
Harness = msg.sender; |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function _getLatestSalt(PoolId poolId) internal returns (uint256) {
|
||
| 47 |
uint256 nextSalt = lpPositionCount[poolId]; |
||
| 48 |
lpPositionCount[poolId] += 1; |
||
| 49 |
return nextSalt; |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function ProvideLiquidity(PoolKey memory poolKey, int24 minTick, int24 maxTick, int256 liqDelta) public returns (uint256 delta0,uint256 delta1) {
|
||
| 53 |
PoolId poolId = poolKey.toId(); |
||
| 54 |
uint256 salt = _getLatestSalt(poolId); |
||
| 55 | |||
| 56 |
uint256 cur0Before = poolKey.currency0.balanceOf(msg.sender); |
||
| 57 |
uint256 cur1Before = poolKey.currency1.balanceOf(msg.sender); |
||
| 58 | |||
| 59 | |||
| 60 |
IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams( |
||
| 61 |
minTick, |
||
| 62 |
maxTick, |
||
| 63 |
liqDelta, |
||
| 64 |
bytes32(salt)); |
||
| 65 |
try manager.unlock(abi.encode(CallbackData(address(this), poolKey, params, new bytes(0), false, false))){}
|
||
| 66 |
catch Error(string memory reason) {
|
||
| 67 |
emit LogString("Error in unlock");
|
||
| 68 |
emit LogString(reason); |
||
| 69 |
assert(false); |
||
| 70 |
} |
||
| 71 |
emit LogUint256("Liquidity provided for position idx", salt);
|
||
| 72 |
emit LogInt256("liquidity", liqDelta);
|
||
| 73 |
delta0 = cur0Before - poolKey.currency0.balanceOf(msg.sender); |
||
| 74 |
delta1 = cur1Before - poolKey.currency1.balanceOf(msg.sender); |
||
| 75 |
emit LogUint256("currency 0 delta", delta0);
|
||
| 76 |
emit LogUint256("currency 1 delta", delta1);
|
||
| 77 |
LpPosition memory lpPosition = lpPositions[poolId][salt]; |
||
| 78 | |||
| 79 |
// technically an invariant null-op since this function always creates new positions. Should also be verified in unlockCallback. |
||
| 80 |
assertGte(liqDelta + int256(lpPosition.liquidity), 0, "Removed more liquidity than was in the position"); |
||
| 81 | |||
| 82 |
lpPositions[poolId][salt] = LpPosition(poolKey, minTick, maxTick, manager.getPosition( |
||
| 83 |
poolId, address(this), minTick, maxTick, bytes32(salt) |
||
| 84 |
).liquidity, bytes32(salt)); |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function proxyApprove(Currency token, address spender) public {
|
||
| 88 |
MockERC20(Currency.unwrap(token)).approve(spender, type(uint256).max); |
||
| 89 |
} |
||
| 90 | |||
| 91 |
struct CallbackData {
|
||
| 92 |
address sender; |
||
| 93 |
PoolKey key; |
||
| 94 |
IPoolManager.ModifyLiquidityParams params; |
||
| 95 |
bytes hookData; |
||
| 96 |
bool settleUsingBurn; |
||
| 97 |
bool takeClaims; |
||
| 98 |
} |
||
| 99 | |||
| 100 |
function unlockCallback(bytes calldata rawData) external override returns (bytes memory) {
|
||
| 101 |
require(msg.sender == address(manager)); |
||
| 102 | |||
| 103 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 104 | |||
| 105 |
uint128 liquidityBefore = manager.getPosition( |
||
| 106 |
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt |
||
| 107 |
).liquidity; |
||
| 108 |
(BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData); |
||
| 109 | |||
| 110 |
uint128 liquidityAfter = manager.getPosition( |
||
| 111 |
data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt |
||
| 112 |
).liquidity; |
||
| 113 | |||
| 114 |
(,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 115 |
(,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 116 | |||
| 117 |
require( |
||
| 118 |
int128(liquidityBefore) + data.params.liquidityDelta == int128(liquidityAfter), "liquidity change incorrect" |
||
| 119 |
); |
||
| 120 | |||
| 121 |
if (data.params.liquidityDelta < 0) {
|
||
| 122 |
assert(delta0 > 0 || delta1 > 0); |
||
| 123 |
assert(!(delta0 < 0 || delta1 < 0)); |
||
| 124 |
} else if (data.params.liquidityDelta > 0) {
|
||
| 125 |
assert(delta0 < 0 || delta1 < 0); |
||
| 126 |
assert(!(delta0 > 0 || delta1 > 0)); |
||
| 127 |
} |
||
| 128 | |||
| 129 |
if (delta0 < 0) {
|
||
| 130 |
// obtain tokens from harness |
||
| 131 |
MockERC20(Currency.unwrap(data.key.currency0)).transferFrom(Harness, address(this), uint256(-delta0)); |
||
| 132 |
CurrencySettler.settle(data.key.currency0, manager, data.sender, uint256(-delta0), data.settleUsingBurn); |
||
| 133 |
} |
||
| 134 |
if (delta1 < 0){
|
||
| 135 |
// obtain tokens from harness |
||
| 136 |
MockERC20(Currency.unwrap(data.key.currency1)).transferFrom(Harness, address(this), uint256(-delta1)); |
||
| 137 |
CurrencySettler.settle(data.key.currency1, manager, data.sender, uint256(-delta1), data.settleUsingBurn); |
||
| 138 |
} |
||
| 139 |
if (delta0 > 0) {
|
||
| 140 |
CurrencySettler.take(data.key.currency0, manager, data.sender, uint256(delta0), data.takeClaims); |
||
| 141 |
// send tokens back to harness |
||
| 142 |
data.key.currency0.transfer(Harness, uint256(delta0)); |
||
| 143 |
} |
||
| 144 |
if (delta1 > 0){
|
||
| 145 |
CurrencySettler.take(data.key.currency1, manager, data.sender, uint256(delta1), data.takeClaims); |
||
| 146 |
// send tokens back to harness |
||
| 147 |
data.key.currency1.transfer( Harness, uint256(delta1)); |
||
| 148 |
} |
||
| 149 | |||
| 150 |
return abi.encode(delta); |
||
| 151 |
} |
||
| 152 | |||
| 153 |
} |
| Lines covered: | 0 / 75 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.0; |
||
| 3 | |||
| 4 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 5 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 6 |
import {Hooks} from "src/libraries/Hooks.sol";
|
||
| 7 |
import {TickMath} from "src/libraries/TickMath.sol";
|
||
| 8 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 9 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 10 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 11 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 12 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 13 |
import {PropertiesAsserts} from "../PropertiesHelper.sol";
|
||
| 14 |
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
|
||
| 15 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 16 |
import {IActor} from "./IActor.sol";
|
||
| 17 |
import {BalanceDelta} from "src/types/BalanceDelta.sol";
|
||
| 18 |
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
|
||
| 19 |
import {PoolTestBase} from "src/test/PoolTestBase.sol";
|
||
| 20 |
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
|
||
| 21 |
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
|
||
| 22 | |||
| 23 |
contract SwapActor is PropertiesAsserts, PoolTestBase, IActor {
|
||
| 24 | |||
| 25 |
using PoolIdLibrary for PoolKey; |
||
| 26 |
using StateLibrary for IPoolManager; |
||
| 27 |
using CurrencyLibrary for Currency; |
||
| 28 |
using Hooks for IHooks; |
||
| 29 |
using LPFeeLibrary for uint24; |
||
| 30 | |||
| 31 |
uint160 internal constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_PRICE + 1; |
||
| 32 |
uint160 internal constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_PRICE - 1; |
||
| 33 | |||
| 34 |
address Harness; |
||
| 35 | |||
| 36 |
constructor(IPoolManager _manager) PoolTestBase(_manager) {
|
||
| 37 |
Harness = msg.sender; |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function proxyApprove(Currency token, address spender) public {
|
||
| 41 |
MockERC20(Currency.unwrap(token)).approve(spender, type(uint256).max); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
struct TestSettings {
|
||
| 45 |
bool takeClaims; |
||
| 46 |
bool settleUsingBurn; |
||
| 47 |
} |
||
| 48 | |||
| 49 |
/// @custom:property After a swap, the actor's fromFunds should decrease or not change, and their toFunds should increase or not change. |
||
| 50 |
/// @custom:precondition PoolKey is an initialized pool. |
||
| 51 |
/// @custom:notes |
||
| 52 |
function swapOneDirection(bool zeroForOne, int256 amount, PoolKey memory poolKey) public returns (SwapInfo memory) {
|
||
| 53 |
Currency fromCurrency = zeroForOne ? poolKey.currency0 : poolKey.currency1; |
||
| 54 |
Currency toCurrency = zeroForOne ? poolKey.currency1 : poolKey.currency0; |
||
| 55 |
SwapInfo memory swap1Results = SwapInfoLibrary.initialize(fromCurrency, toCurrency, address(Harness)); |
||
| 56 | |||
| 57 |
IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
|
||
| 58 |
zeroForOne: zeroForOne, |
||
| 59 |
amountSpecified: amount, |
||
| 60 |
sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT |
||
| 61 |
}); |
||
| 62 |
TestSettings memory settings = TestSettings({takeClaims: false, settleUsingBurn: false});
|
||
| 63 | |||
| 64 |
abi.decode( |
||
| 65 |
manager.unlock(abi.encode(CallbackData(address(this), settings, poolKey, params, new bytes(0)))), (BalanceDelta) |
||
| 66 |
); |
||
| 67 | |||
| 68 |
swap1Results.captureSwapResults(); |
||
| 69 |
emit LogInt256("a Swap amount", amount);
|
||
| 70 |
emit LogInt256("a Swap fromDelta", swap1Results.fromDelta);
|
||
| 71 |
emit LogInt256("a Swap toDelta", swap1Results.toDelta);
|
||
| 72 | |||
| 73 |
assertWithMsg(swap1Results.fromDelta <= 0, "fromDelta <= 0"); |
||
| 74 |
assertWithMsg(swap1Results.toDelta >= 0, "toDelta >= 0"); |
||
| 75 | |||
| 76 |
return swap1Results; |
||
| 77 |
} |
||
| 78 | |||
| 79 |
/// @custom:property After a bi-directional swap, the actor's fromFunds should decrease and their toFunds should decrease or not change. |
||
| 80 |
/// @custom:precondition PoolKey is an initialized pool. |
||
| 81 |
/// @custom:notes |
||
| 82 |
function swapBiDirectional(bool zeroForOne, int256 amount, PoolKey memory poolKey) public {
|
||
| 83 |
if(amount < 0){
|
||
| 84 |
amount = amount * -1; |
||
| 85 |
} |
||
| 86 |
SwapInfo memory swap1Results = swapOneDirection(zeroForOne, amount, poolKey); |
||
| 87 | |||
| 88 |
// now swap in the opposite direction using the exact amount we received |
||
| 89 |
int256 newAmount = -1 * swap1Results.toDelta; |
||
| 90 |
require(newAmount != 0); |
||
| 91 | |||
| 92 |
SwapInfo memory swap2Results = swapOneDirection(!zeroForOne, newAmount, poolKey); |
||
| 93 | |||
| 94 |
// now actually verify the property |
||
| 95 |
int256 fromBalanceDifference = swap2Results.toBalanceAfter - swap1Results.fromBalanceBefore; |
||
| 96 |
int256 toBalanceDifference = swap2Results.fromBalanceAfter - swap1Results.toBalanceBefore; |
||
| 97 |
emit LogInt256("fromBalanceDifference", fromBalanceDifference);
|
||
| 98 |
emit LogInt256("toBalanceDifference", toBalanceDifference);
|
||
| 99 | |||
| 100 |
assertLt(fromBalanceDifference, 0, "Must not have more tokens than started with (from)"); |
||
| 101 |
assertLte(toBalanceDifference, 0, "Must not have more tokens than started with (to)"); |
||
| 102 |
} |
||
| 103 |
|
||
| 104 |
struct CallbackData {
|
||
| 105 |
address sender; |
||
| 106 |
TestSettings testSettings; |
||
| 107 |
PoolKey key; |
||
| 108 |
IPoolManager.SwapParams params; |
||
| 109 |
bytes hookData; |
||
| 110 |
} |
||
| 111 | |||
| 112 |
function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
|
||
| 113 |
require(msg.sender == address(manager)); |
||
| 114 |
CallbackData memory data = abi.decode(rawData, (CallbackData)); |
||
| 115 | |||
| 116 |
(,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 117 |
(,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 118 | |||
| 119 |
assertWithMsg(deltaBefore0 == 0, "deltaBefore0 is not equal to 0"); |
||
| 120 |
assertWithMsg(deltaBefore1 == 0, "deltaBefore1 is not equal to 0"); |
||
| 121 | |||
| 122 |
BalanceDelta delta = manager.swap(data.key, data.params, data.hookData); |
||
| 123 | |||
| 124 |
(,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this)); |
||
| 125 |
(,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this)); |
||
| 126 | |||
| 127 |
if (data.params.zeroForOne) {
|
||
| 128 |
if (data.params.amountSpecified < 0) {
|
||
| 129 |
// exact input, 0 for 1 |
||
| 130 |
assertWithMsg( |
||
| 131 |
deltaAfter0 >= data.params.amountSpecified, |
||
| 132 |
"deltaAfter0 is not greater than or equal to data.params.amountSpecified" |
||
| 133 |
); |
||
| 134 |
assertWithMsg(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0"); |
||
| 135 |
assertWithMsg(deltaAfter1 >= 0, "deltaAfter1 is not greater than or equal to 0"); |
||
| 136 |
} else {
|
||
| 137 |
// exact output, 0 for 1 |
||
| 138 |
assertWithMsg(deltaAfter0 <= 0, "deltaAfter0 is not less than or equal to zero"); |
||
| 139 |
assertWithMsg(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1"); |
||
| 140 |
assertWithMsg( |
||
| 141 |
deltaAfter1 <= data.params.amountSpecified, |
||
| 142 |
"deltaAfter1 is not less than or equal to data.params.amountSpecified" |
||
| 143 |
); |
||
| 144 |
} |
||
| 145 |
} else {
|
||
| 146 |
if (data.params.amountSpecified < 0) {
|
||
| 147 |
// exact input, 1 for 0 |
||
| 148 |
assertWithMsg( |
||
| 149 |
deltaAfter1 >= data.params.amountSpecified, |
||
| 150 |
"deltaAfter1 is not greater than or equal to data.params.amountSpecified" |
||
| 151 |
); |
||
| 152 |
assertWithMsg(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1"); |
||
| 153 |
assertWithMsg(deltaAfter0 >= 0, "deltaAfter0 is not greater than or equal to 0"); |
||
| 154 |
} else {
|
||
| 155 |
// exact output, 1 for 0 |
||
| 156 |
assertWithMsg(deltaAfter1 <= 0, "deltaAfter1 is not less than or equal to 0"); |
||
| 157 |
assertWithMsg(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0"); |
||
| 158 |
assertWithMsg( |
||
| 159 |
deltaAfter0 <= data.params.amountSpecified, |
||
| 160 |
"deltaAfter0 is not less than or equal to data.params.amountSpecified" |
||
| 161 |
); |
||
| 162 |
} |
||
| 163 |
} |
||
| 164 | |||
| 165 | |||
| 166 |
if (deltaAfter0 < 0) {
|
||
| 167 |
// obtain tokens from harness |
||
| 168 |
MockERC20(Currency.unwrap(data.key.currency0)).transferFrom(Harness, address(this), uint256(-deltaAfter0)); |
||
| 169 |
CurrencySettler.settle(data.key.currency0, manager, data.sender, uint256(-deltaAfter0), false); |
||
| 170 |
} |
||
| 171 |
if (deltaAfter1 < 0) {
|
||
| 172 |
// obtain tokens from harness |
||
| 173 |
MockERC20(Currency.unwrap(data.key.currency1)).transferFrom(Harness, address(this), uint256(-deltaAfter1)); |
||
| 174 |
CurrencySettler.settle(data.key.currency1, manager, data.sender, uint256(-deltaAfter1), false); |
||
| 175 |
} |
||
| 176 |
if (deltaAfter0 > 0) {
|
||
| 177 |
CurrencySettler.take(data.key.currency0, manager, data.sender, uint256(deltaAfter0), false); |
||
| 178 |
// send tokens back to harness |
||
| 179 |
data.key.currency0.transfer(Harness, uint256(deltaAfter0)); |
||
| 180 |
} |
||
| 181 |
if (deltaAfter1 > 0) {
|
||
| 182 |
CurrencySettler.take(data.key.currency1, manager, data.sender, uint256(deltaAfter1), false); |
||
| 183 |
// send tokens back to harness |
||
| 184 |
data.key.currency1.transfer( Harness, uint256(deltaAfter1)); |
||
| 185 |
} |
||
| 186 | |||
| 187 |
return abi.encode(delta); |
||
| 188 |
} |
||
| 189 |
} |
| Lines covered: | 0 / 180 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.13; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 |
import "forge-std/console2.sol"; |
||
| 6 |
import "test/trailofbits/ActionFuzzEntrypoint.sol"; |
||
| 7 | |||
| 8 |
import {Pool} from "src/libraries/Pool.sol";
|
||
| 9 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 10 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 11 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 12 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 13 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 14 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 15 |
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
|
||
| 16 | |||
| 17 |
/// @notice This test contract gives us a way to detect potential regressions in the Actions fuzzing harness and |
||
| 18 |
/// explitily test regression sequences that were caused by false positives. |
||
| 19 |
contract ActionsHarness_Test is Test {
|
||
| 20 |
ActionFuzzEntrypoint target; |
||
| 21 |
using Pool for IPoolManager; |
||
| 22 |
using PoolIdLibrary for PoolKey; |
||
| 23 |
using TransientStateLibrary for IPoolManager; |
||
| 24 |
using StateLibrary for IPoolManager; |
||
| 25 | |||
| 26 |
function setUp() public {
|
||
| 27 |
target = new ActionFuzzEntrypoint(); |
||
| 28 |
payable(address(target)).transfer(address(this).balance - 20 ether); |
||
| 29 |
payable(address(target.getActionRouter())).transfer(20 ether); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function test_sync_test() public {
|
||
| 33 |
target.addSync(uint8(0)); |
||
| 34 |
} |
||
| 35 |
|
||
| 36 |
function test_initialize_and_add_liquidity_settle() public {
|
||
| 37 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 38 |
target.addSync(uint8(0)); |
||
| 39 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 40 |
target.addSettle(); |
||
| 41 |
target.addSync(uint8(1)); |
||
| 42 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 43 |
target.addSettle(); |
||
| 44 |
target.runActions(); |
||
| 45 |
} |
||
| 46 | |||
| 47 |
function test_initialize_and_add_liquidity_settle_for() public {
|
||
| 48 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 49 |
target.addSync(uint8(0)); |
||
| 50 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 51 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 52 |
target.addSync(uint8(1)); |
||
| 53 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 54 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 55 |
target.runActions(); |
||
| 56 |
} |
||
| 57 | |||
| 58 |
function test_donate() public {
|
||
| 59 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 60 |
target.addSync(uint8(0)); |
||
| 61 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 62 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 63 |
target.addSync(uint8(1)); |
||
| 64 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 65 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 66 |
target.runActions(); |
||
| 67 | |||
| 68 |
target.addDonate(0, 0.5 ether, 0.5 ether); |
||
| 69 |
target.addSync(uint8(0)); |
||
| 70 |
target.addTransferFrom(0, 0.5 ether, address(target), address(target.getManager())); |
||
| 71 |
target.addSettle(); |
||
| 72 |
target.addSync(uint8(1)); |
||
| 73 |
target.addTransferFrom(1, 0.5 ether, address(target), address(target.getManager())); |
||
| 74 |
target.addSettle(); |
||
| 75 |
target.runActions(); |
||
| 76 |
} |
||
| 77 |
|
||
| 78 |
function test_take_settle() public {
|
||
| 79 |
target.addSync(uint8(0)); |
||
| 80 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 81 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 82 |
target.addSync(uint8(0)); |
||
| 83 |
target.addTake(0, 1 ether); |
||
| 84 |
target.runActions(); |
||
| 85 | |||
| 86 |
} |
||
| 87 | |||
| 88 |
function test_swap() public {
|
||
| 89 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 90 |
target.addSync(uint8(0)); |
||
| 91 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 92 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 93 |
target.addSync(uint8(1)); |
||
| 94 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 95 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 96 |
target.runActions(); |
||
| 97 | |||
| 98 |
target.addSwap(0, -0.5 ether, true); |
||
| 99 |
target.addSync(uint8(0)); |
||
| 100 |
target.addTransferFrom(0, 0.5 ether, address(target) , address(target.getManager())); |
||
| 101 |
target.addSettle(); |
||
| 102 | |||
| 103 |
target.addSync(uint8(1)); |
||
| 104 |
target.addTake(1, 333333333333333313); |
||
| 105 |
target.runActions(); |
||
| 106 | |||
| 107 |
} |
||
| 108 | |||
| 109 |
function test_swap2() public {
|
||
| 110 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 111 |
target.addSync(uint8(0)); |
||
| 112 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 113 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 114 |
target.addSync(uint8(1)); |
||
| 115 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 116 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 117 |
target.runActions(); |
||
| 118 | |||
| 119 |
target.addSwap(0, -0.5 ether, false); |
||
| 120 |
target.addSync(uint8(1)); |
||
| 121 |
target.addTransferFrom(1, 0.5 ether, address(target) , address(target.getManager())); |
||
| 122 |
target.addSettle(); |
||
| 123 | |||
| 124 |
target.addSync(uint8(0)); |
||
| 125 |
target.addTake(0, 333333333333333311); |
||
| 126 |
target.runActions(); |
||
| 127 | |||
| 128 |
} |
||
| 129 | |||
| 130 |
function test_mint() public {
|
||
| 131 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 132 |
target.addSync(uint8(0)); |
||
| 133 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 134 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 135 |
target.addSync(uint8(1)); |
||
| 136 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 137 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 138 |
target.runActions(); |
||
| 139 | |||
| 140 |
target.addSwap(0, -0.5 ether, false); |
||
| 141 |
target.addSync(uint8(1)); |
||
| 142 |
target.addTransferFrom(1, 0.5 ether, address(target) , address(target.getManager())); |
||
| 143 |
target.addSettle(); |
||
| 144 | |||
| 145 |
target.addSync(uint8(0)); |
||
| 146 |
target.addMint(address(target), 0, 333333333333333311); |
||
| 147 |
target.runActions(); |
||
| 148 | |||
| 149 |
} |
||
| 150 | |||
| 151 |
function test_settle_native() public {
|
||
| 152 |
uint8 nativeCurrencyIdx = uint8(target.NUMBER_CURRENCIES()-1); |
||
| 153 | |||
| 154 |
target.addInitializeAndAddLiquidity(0, nativeCurrencyIdx, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 155 |
target.addSync(uint8(0)); |
||
| 156 | |||
| 157 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 158 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 159 | |||
| 160 |
target.addSync(uint8(nativeCurrencyIdx)); |
||
| 161 |
target.addSettleNative(1 ether); |
||
| 162 |
target.runActions(); |
||
| 163 | |||
| 164 |
target.addSwap(0, -0.5 ether, true); |
||
| 165 |
target.addSync(nativeCurrencyIdx); |
||
| 166 |
target.addSettleNative(0.5 ether); |
||
| 167 | |||
| 168 |
target.addSync(uint8(0)); |
||
| 169 |
target.addTake(0, 333333333333333313); |
||
| 170 |
target.runActions(); |
||
| 171 |
} |
||
| 172 | |||
| 173 |
function test_addShortcutSettle() public {
|
||
| 174 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 175 |
target.addSync(uint8(0)); |
||
| 176 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 177 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 178 |
target.addSync(uint8(1)); |
||
| 179 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 180 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 181 |
target.runActions(); |
||
| 182 | |||
| 183 |
target.addSwap(0, -0.5 ether, false); |
||
| 184 |
target.addShortcutSettle(); |
||
| 185 |
target.runActions(); |
||
| 186 |
} |
||
| 187 | |||
| 188 |
function test_burn() public {
|
||
| 189 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 190 |
target.addSync(uint8(0)); |
||
| 191 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 192 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 193 |
target.addSync(uint8(1)); |
||
| 194 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 195 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 196 |
target.runActions(); |
||
| 197 | |||
| 198 | |||
| 199 |
target.addSync(uint8(0)); |
||
| 200 |
target.addMint(address(target.getActionRouter()), 0, 1 ether); |
||
| 201 |
target.addBurn(address(target.getActionRouter()), 0, 1 ether); |
||
| 202 |
|
||
| 203 |
target.addSettle(); |
||
| 204 |
target.runActions(); |
||
| 205 |
} |
||
| 206 | |||
| 207 |
function test_clear() public {
|
||
| 208 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 209 |
target.addSync(uint8(0)); |
||
| 210 |
target.addTransferFrom(0, 1 ether, address(target), address(target.getManager())); |
||
| 211 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 212 |
target.addSync(uint8(1)); |
||
| 213 |
target.addTransferFrom(1, 1 ether, address(target), address(target.getManager())); |
||
| 214 |
target.addSettleFor(address(target.getActionRouter())); |
||
| 215 |
target.runActions(); |
||
| 216 | |||
| 217 |
target.addSwap(0, -0.5 ether, false); |
||
| 218 |
target.addSync(uint8(1)); |
||
| 219 |
target.addTransferFrom(1, 0.5 ether, address(target) , address(target.getManager())); |
||
| 220 |
target.addSettle(); |
||
| 221 | |||
| 222 |
target.addSync(uint8(0)); |
||
| 223 |
target.addClear(0, 333333333333333311); |
||
| 224 |
target.runActions(); |
||
| 225 |
} |
||
| 226 | |||
| 227 |
function test_swapin_out() public {
|
||
| 228 |
target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0); |
||
| 229 |
target.addSwapInSwapOut(0, true, 1 ether); |
||
| 230 |
target.runActions(); |
||
| 231 |
} |
||
| 232 | |||
| 233 |
function test_feegrowth_overflow() public {
|
||
| 234 |
int128 amount = 1; |
||
| 235 |
target.addInitializeAndAddLiquidityAndSettle(0, 1, 1, 79228162514264337593543950336, 1_000_000, 0, 1 , amount, 0); |
||
| 236 |
PoolId poolId = abi.decode(hex"ad005400d48c3dc36756210997b5869d257ca207f4d5085e1bd29919092d6a97", (PoolId)); |
||
| 237 |
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = IPoolManager(target.getManager()).getFeeGrowthInside(poolId, 0, 1); |
||
| 238 |
|
||
| 239 |
for(uint i=0; i<3; i++) {
|
||
| 240 |
console2.logUint(i); |
||
| 241 |
target.addDonate(0, uint128(type(int128).max), uint128(type(int128).max)); |
||
| 242 |
target.addShortcutSettle(); |
||
| 243 |
target.runActions(); |
||
| 244 |
} |
||
| 245 | |||
| 246 |
(feeGrowthInside0X128, feeGrowthInside1X128) = IPoolManager(target.getManager()).getFeeGrowthInside(poolId, 0, 1); |
||
| 247 | |||
| 248 |
console2.logUint(feeGrowthInside0X128/FixedPoint128.Q128); |
||
| 249 |
console2.logUint(feeGrowthInside1X128/FixedPoint128.Q128); |
||
| 250 | |||
| 251 |
} |
||
| 252 | |||
| 253 |
function test_targeted_pool() public {
|
||
| 254 |
target.addTargetedPoolReadyToOverflow(0, 1, 0); |
||
| 255 | |||
| 256 |
} |
||
| 257 | |||
| 258 |
function test_fee_miscalculation_regression() public {
|
||
| 259 |
target.addTargetedPool(1,0,0,99); |
||
| 260 |
target.addModifyPositionAndRunActions(0,0,-1,934735867213017,13541478287070347540639706863682772478921284014365313132303827141936693186); |
||
| 261 |
target.addSetNewProtocolFee(0,1); |
||
| 262 |
target.addSwapAndRunActions(0,4110922,true); |
||
| 263 |
} |
||
| 264 | |||
| 265 |
function test_shadowaccounting_regression_1() public {
|
||
| 266 |
target.addTargetedPool(0,3,0,273233); |
||
| 267 |
target.addModifyPositionAndRunActions(0,-2,0,248701260024546,1115970101497554417622751038604682045916585273685975242110649999204994190); |
||
| 268 |
target.addSetNewProtocolFee(0,1); |
||
| 269 |
target.addSwapAndRunActions(0,33216723,true); |
||
| 270 |
} |
||
| 271 | |||
| 272 |
function test_shadowaccounting_regression_2() public {
|
||
| 273 |
target.addTargetedPool(1,0,0,1); |
||
| 274 |
target.addModifyPositionAndRunActions(0,-1001,-161,1478484426,115792089237316195423570985008687907853269984665640564039457584007913129637888); |
||
| 275 |
target.addSwapAndRunActions(0,1,true); |
||
| 276 |
target.addDonateAndSettle(0,2); |
||
| 277 |
target.addModifyPositionAndRunActions(0,-1001,-161,277295330,115792089237316195423570985008687907853269984665640564039457584007913129637888); |
||
| 278 |
} |
||
| 279 | |||
| 280 |
function test_shadowaccounting_regression_3() public {
|
||
| 281 |
target.addTargetedPool(0,59,1,-335483349064151699904); |
||
| 282 |
target.addModifyPosition(35,0,17096,53,82970313381531717844305482713703611020253841721915); |
||
| 283 |
target.addSettleFor(address(0)); |
||
| 284 |
target.addBurnAndRunActions(address(0),16,0); |
||
| 285 |
} |
||
| 286 | |||
| 287 |
function test_shadowaccounting_regression_4() public {
|
||
| 288 |
target.addSync(0); |
||
| 289 |
vm.roll(block.number + 38894); |
||
| 290 |
target.runActions(); |
||
| 291 |
vm.roll(block.number + 38894); |
||
| 292 |
target.addSettleFor(address(0)); |
||
| 293 |
vm.roll(block.number + 38894); |
||
| 294 |
target.runActions(); |
||
| 295 | |||
| 296 |
} |
||
| 297 | |||
| 298 |
function test_swap_through_fee_overflow_pool() public {
|
||
| 299 |
target.addTargetedPoolReadyToOverflow(1,0,1); |
||
| 300 |
target.addModifyPosition(0,2,1,1,2367934173550170961037218246786631748697795); |
||
| 301 |
target.addSwap(0,-3,false); |
||
| 302 |
target.addDonateAndSettle(0,0); |
||
| 303 |
} |
||
| 304 |
|
||
| 305 | |||
| 306 |
function test_swap_through_fee_overflow_pool2() public {
|
||
| 307 |
target.addTargetedPoolReadyToOverflow(1,0,1); |
||
| 308 |
target.addModifyPosition(0,0,1,2,2367934173550170961037218246786631748697795); |
||
| 309 |
target.addDonateAndSettle(5,5); |
||
| 310 |
target.addSwap(0,-3,false); |
||
| 311 |
target.addShortcutSettle(); |
||
| 312 |
target.runActions(); |
||
| 313 |
} |
||
| 314 | |||
| 315 |
function test_poolliquidity_regression_1() public {
|
||
| 316 |
target.addTargetedPoolReadyToOverflow(247, 0, 6909592); |
||
| 317 |
target.addModifyPositionAndRunActions(0, -14, 2530466, 2812, 115792089237316195423570985008687907853269984665640564039457584007913129638913); |
||
| 318 |
target.addSwapAndRunActions(0, 92274097787679228392889020467702269147, false); |
||
| 319 |
target.addModifyPositionAndRunActions(0, -14, 2530466, 793, 115792089237316195423570985008687907853269984665640564039457584007913129638913); |
||
| 320 |
} |
||
| 321 | |||
| 322 |
function test_assert111() public {
|
||
| 323 | |||
| 324 |
} |
||
| 325 | |||
| 326 |
} |
||
| 327 | |||
| 328 |
|
| Lines covered: | 0 / 50 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.13; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 |
import "forge-std/console2.sol"; |
||
| 6 |
import "test/trailofbits/ActionFuzzEntrypoint.sol"; |
||
| 7 |
import "test/trailofbits/PropertiesHelper.sol"; |
||
| 8 | |||
| 9 |
import {Pool} from "src/libraries/Pool.sol";
|
||
| 10 |
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
|
||
| 11 |
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
|
||
| 12 |
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
|
||
| 13 |
import {PoolKey} from "src/types/PoolKey.sol";
|
||
| 14 |
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
|
||
| 15 |
import {StateLibrary} from "src/libraries/StateLibrary.sol";
|
||
| 16 |
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
|
||
| 17 | |||
| 18 |
/// @notice This test contract gives us a way to detect potential regressions in the Actions fuzzing harness and |
||
| 19 |
/// explitily test regression sequences that were caused by false positives. |
||
| 20 | |||
| 21 |
contract Tmp is PropertiesAsserts {
|
||
| 22 |
function assertGtInt(int256 a, int256 b, string memory reason) public {
|
||
| 23 |
assertGt(a,b, reason); |
||
| 24 |
} |
||
| 25 | |||
| 26 |
function assertGteInt(int256 a, int256 b, string memory reason) public {
|
||
| 27 |
assertGte(a,b, reason); |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function assertLtInt(int256 a, int256 b, string memory reason) public {
|
||
| 31 |
assertLt(a,b, reason); |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function assertLteInt(int256 a, int256 b, string memory reason) public {
|
||
| 35 |
assertLte(a,b, reason); |
||
| 36 |
} |
||
| 37 | |||
| 38 |
function assertGtUInt(uint256 a, uint256 b, string memory reason) public {
|
||
| 39 |
assertGt(a,b, reason); |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function assertGteUInt(uint256 a, uint256 b, string memory reason) public {
|
||
| 43 |
assertGte(a,b, reason); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function assertLtUInt(uint256 a, uint256 b, string memory reason) public {
|
||
| 47 |
assertLt(a,b, reason); |
||
| 48 |
} |
||
| 49 | |||
| 50 |
function assertLteUInt(uint256 a, uint256 b, string memory reason) public {
|
||
| 51 |
assertLte(a,b, reason); |
||
| 52 |
} |
||
| 53 | |||
| 54 |
} |
||
| 55 | |||
| 56 |
contract Regression_Test is Test {
|
||
| 57 |
ActionFuzzEntrypoint target; |
||
| 58 |
using Pool for IPoolManager; |
||
| 59 |
using PoolIdLibrary for PoolKey; |
||
| 60 |
using TransientStateLibrary for IPoolManager; |
||
| 61 |
using StateLibrary for IPoolManager; |
||
| 62 | |||
| 63 |
function setUp() public {
|
||
| 64 |
target = new ActionFuzzEntrypoint(); |
||
| 65 |
payable(address(target)).transfer(address(this).balance - 20 ether); |
||
| 66 |
payable(address(target.getActionRouter())).transfer(20 ether); |
||
| 67 |
} |
||
| 68 | |||
| 69 |
function _calcDiffInt256(int256 a, int256 b) internal returns (uint256) {
|
||
| 70 |
if (b > a) {
|
||
| 71 |
int256 tmp = a; |
||
| 72 |
a = b; |
||
| 73 |
b = tmp; |
||
| 74 |
} |
||
| 75 |
uint256 trueDiff; |
||
| 76 |
unchecked {
|
||
| 77 |
int256 diff = a - b; |
||
| 78 |
if(diff >= 0) {
|
||
| 79 |
emit LogString("non overflow path");
|
||
| 80 |
trueDiff = uint256(diff); |
||
| 81 |
} else {
|
||
| 82 |
emit LogString("overflow");
|
||
| 83 |
a -= type(int256).max; |
||
| 84 |
emit LogInt256("a", a);
|
||
| 85 |
emit LogInt256("b", b);
|
||
| 86 |
emit LogUint256("diffpre", (uint256(a-b)));
|
||
| 87 |
trueDiff = uint256(a - b) + uint256(type(int256).max); |
||
| 88 |
} |
||
| 89 |
} |
||
| 90 |
return trueDiff; |
||
| 91 |
} |
||
| 92 | |||
| 93 |
event LogUint256(string, uint256); |
||
| 94 |
event LogInt256(string, int256); |
||
| 95 |
event LogAddress(string, address); |
||
| 96 |
event LogString(string); |
||
| 97 |
event LogBytes(bytes); |
||
| 98 | |||
| 99 |
function test_int_differ() public {
|
||
| 100 |
int256 a = type(int256).max; |
||
| 101 |
int256 b = type(int256).min; |
||
| 102 |
uint256 d = _calcDiffInt256(a,b); |
||
| 103 |
uint256 e = _calcDiffInt256(b,a); |
||
| 104 |
assert(d == e); |
||
| 105 |
emit LogUint256("diff", e);
|
||
| 106 |
emit LogUint256("max",type(uint256).max);
|
||
| 107 | |||
| 108 |
assert(d == type(uint256).max); |
||
| 109 |
} |
||
| 110 | |||
| 111 |
function test_int() public {
|
||
| 112 |
Tmp t = new Tmp(); |
||
| 113 |
int256 a = type(int256).max; |
||
| 114 |
int256 b = type(int256).min; |
||
| 115 |
t.assertGtInt(a,b, "test 1"); |
||
| 116 |
t.assertGteInt(a,b, "test 2"); |
||
| 117 | |||
| 118 |
t.assertLtInt(b,a, "test 3"); |
||
| 119 |
t.assertLteInt(b,a, "test 4"); |
||
| 120 |
} |
||
| 121 | |||
| 122 |
function test_uint() public {
|
||
| 123 |
Tmp t = new Tmp(); |
||
| 124 |
uint256 a = type(uint256).max; |
||
| 125 |
uint256 b = type(uint256).min; |
||
| 126 |
t.assertGtUInt(a,b, "test 1"); |
||
| 127 |
t.assertGteUInt(a,b, "test 2"); |
||
| 128 | |||
| 129 |
t.assertLtUInt(b,a, "test 3"); |
||
| 130 |
t.assertLteUInt(b,a, "test 4"); |
||
| 131 |
} |
||
| 132 | |||
| 133 |
} |
||
| 134 | |||
| 135 |
|
| Lines covered: | 0 / 68 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {BalanceDelta, toBalanceDelta} from "../../src/types/BalanceDelta.sol";
|
||
| 6 | |||
| 7 |
contract TestBalanceDelta is Test {
|
||
| 8 |
function test_toBalanceDelta() public pure {
|
||
| 9 |
BalanceDelta balanceDelta = toBalanceDelta(0, 0); |
||
| 10 |
assertEq(balanceDelta.amount0(), 0); |
||
| 11 |
assertEq(balanceDelta.amount1(), 0); |
||
| 12 | |||
| 13 |
balanceDelta = toBalanceDelta(0, 1); |
||
| 14 |
assertEq(balanceDelta.amount0(), 0); |
||
| 15 |
assertEq(balanceDelta.amount1(), 1); |
||
| 16 | |||
| 17 |
balanceDelta = toBalanceDelta(1, 0); |
||
| 18 |
assertEq(balanceDelta.amount0(), 1); |
||
| 19 |
assertEq(balanceDelta.amount1(), 0); |
||
| 20 | |||
| 21 |
balanceDelta = toBalanceDelta(type(int128).max, type(int128).max); |
||
| 22 |
assertEq(balanceDelta.amount0(), type(int128).max); |
||
| 23 |
assertEq(balanceDelta.amount1(), type(int128).max); |
||
| 24 | |||
| 25 |
balanceDelta = toBalanceDelta(type(int128).min, type(int128).min); |
||
| 26 |
assertEq(balanceDelta.amount0(), type(int128).min); |
||
| 27 |
assertEq(balanceDelta.amount1(), type(int128).min); |
||
| 28 |
} |
||
| 29 | |||
| 30 |
function test_fuzz_toBalanceDelta(int128 x, int128 y) public pure {
|
||
| 31 |
BalanceDelta balanceDelta = toBalanceDelta(x, y); |
||
| 32 |
int256 expectedBD = int256(uint256(bytes32(abi.encodePacked(x, y)))); |
||
| 33 |
assertEq(BalanceDelta.unwrap(balanceDelta), expectedBD); |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function test_fuzz_amount0_amount1(int128 x, int128 y) public pure {
|
||
| 37 |
BalanceDelta balanceDelta = toBalanceDelta(x, y); |
||
| 38 |
assertEq(balanceDelta.amount0(), x); |
||
| 39 |
assertEq(balanceDelta.amount1(), y); |
||
| 40 |
} |
||
| 41 | |||
| 42 |
function test_add() public pure {
|
||
| 43 |
BalanceDelta balanceDelta = toBalanceDelta(0, 0) + toBalanceDelta(0, 0); |
||
| 44 |
assertEq(balanceDelta.amount0(), 0); |
||
| 45 |
assertEq(balanceDelta.amount1(), 0); |
||
| 46 | |||
| 47 |
balanceDelta = toBalanceDelta(-1000, 1000) + toBalanceDelta(1000, -1000); |
||
| 48 |
assertEq(balanceDelta.amount0(), 0); |
||
| 49 |
assertEq(balanceDelta.amount1(), 0); |
||
| 50 | |||
| 51 |
balanceDelta = |
||
| 52 |
toBalanceDelta(type(int128).min, type(int128).max) + toBalanceDelta(type(int128).max, type(int128).min); |
||
| 53 |
assertEq(balanceDelta.amount0(), -1); |
||
| 54 |
assertEq(balanceDelta.amount1(), -1); |
||
| 55 | |||
| 56 |
balanceDelta = toBalanceDelta(type(int128).max / 2 + 1, type(int128).max / 2 + 1) |
||
| 57 |
+ toBalanceDelta(type(int128).max / 2, type(int128).max / 2); |
||
| 58 |
assertEq(balanceDelta.amount0(), type(int128).max); |
||
| 59 |
assertEq(balanceDelta.amount1(), type(int128).max); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function test_add_revertsOnOverflow() public {
|
||
| 63 |
// should revert because type(int128).max + 1 is not possible |
||
| 64 |
vm.expectRevert(); |
||
| 65 |
toBalanceDelta(type(int128).max, 0) + toBalanceDelta(1, 0); |
||
| 66 | |||
| 67 |
vm.expectRevert(); |
||
| 68 |
toBalanceDelta(0, type(int128).max) + toBalanceDelta(0, 1); |
||
| 69 |
} |
||
| 70 | |||
| 71 |
function test_fuzz_add(int128 a, int128 b, int128 c, int128 d) public {
|
||
| 72 |
int256 ac = int256(a) + c; |
||
| 73 |
int256 bd = int256(b) + d; |
||
| 74 | |||
| 75 |
// if the addition overflows it should revert |
||
| 76 |
if (ac != int128(ac) || bd != int128(bd)) {
|
||
| 77 |
vm.expectRevert(); |
||
| 78 |
} |
||
| 79 | |||
| 80 |
BalanceDelta balanceDelta = toBalanceDelta(a, b) + toBalanceDelta(c, d); |
||
| 81 |
assertEq(balanceDelta.amount0(), ac); |
||
| 82 |
assertEq(balanceDelta.amount1(), bd); |
||
| 83 |
} |
||
| 84 | |||
| 85 |
function test_sub() public pure {
|
||
| 86 |
BalanceDelta balanceDelta = toBalanceDelta(0, 0) - toBalanceDelta(0, 0); |
||
| 87 |
assertEq(balanceDelta.amount0(), 0); |
||
| 88 |
assertEq(balanceDelta.amount1(), 0); |
||
| 89 | |||
| 90 |
balanceDelta = toBalanceDelta(-1000, 1000) - toBalanceDelta(1000, -1000); |
||
| 91 |
assertEq(balanceDelta.amount0(), -2000); |
||
| 92 |
assertEq(balanceDelta.amount1(), 2000); |
||
| 93 | |||
| 94 |
balanceDelta = |
||
| 95 |
toBalanceDelta(-1000, -1000) - toBalanceDelta(-(type(int128).min + 1000), -(type(int128).min + 1000)); |
||
| 96 |
assertEq(balanceDelta.amount0(), type(int128).min); |
||
| 97 |
assertEq(balanceDelta.amount1(), type(int128).min); |
||
| 98 | |||
| 99 |
balanceDelta = toBalanceDelta(type(int128).min / 2, type(int128).min / 2) |
||
| 100 |
- toBalanceDelta(-(type(int128).min / 2), -(type(int128).min / 2)); |
||
| 101 |
assertEq(balanceDelta.amount0(), type(int128).min); |
||
| 102 |
assertEq(balanceDelta.amount1(), type(int128).min); |
||
| 103 |
} |
||
| 104 | |||
| 105 |
function test_sub_revertsOnUnderflow() public {
|
||
| 106 |
// should revert because type(int128).min - 1 is not possible |
||
| 107 |
vm.expectRevert(); |
||
| 108 |
toBalanceDelta(type(int128).min, 0) - toBalanceDelta(1, 0); |
||
| 109 | |||
| 110 |
vm.expectRevert(); |
||
| 111 |
toBalanceDelta(0, type(int128).min) - toBalanceDelta(0, 1); |
||
| 112 |
} |
||
| 113 | |||
| 114 |
function test_fuzz_sub(int128 a, int128 b, int128 c, int128 d) public {
|
||
| 115 |
int256 ac = int256(a) - c; |
||
| 116 |
int256 bd = int256(b) - d; |
||
| 117 | |||
| 118 |
// if the subtraction underflows it should revert |
||
| 119 |
if (ac != int128(ac) || bd != int128(bd)) {
|
||
| 120 |
vm.expectRevert(); |
||
| 121 |
} |
||
| 122 | |||
| 123 |
BalanceDelta balanceDelta = toBalanceDelta(a, b) - toBalanceDelta(c, d); |
||
| 124 |
assertEq(balanceDelta.amount0(), ac); |
||
| 125 |
assertEq(balanceDelta.amount1(), bd); |
||
| 126 |
} |
||
| 127 | |||
| 128 |
function test_fuzz_eq(int128 a, int128 b, int128 c, int128 d) public pure {
|
||
| 129 |
bool isEqual = (toBalanceDelta(a, b) == toBalanceDelta(c, d)); |
||
| 130 |
if (a == c && b == d) assertTrue(isEqual); |
||
| 131 |
else assertFalse(isEqual); |
||
| 132 |
} |
||
| 133 | |||
| 134 |
function test_fuzz_neq(int128 a, int128 b, int128 c, int128 d) public pure {
|
||
| 135 |
bool isNotEqual = (toBalanceDelta(a, b) != toBalanceDelta(c, d)); |
||
| 136 |
if (a != c || b != d) assertTrue(isNotEqual); |
||
| 137 |
else assertFalse(isNotEqual); |
||
| 138 |
} |
||
| 139 |
} |
||
| 140 |
| Lines covered: | 0 / 66 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {stdError} from "forge-std/StdError.sol";
|
||
| 6 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 7 |
import {Currency, CurrencyLibrary} from "../../src/types/Currency.sol";
|
||
| 8 |
import {CurrencyTest} from "../../src/test/CurrencyTest.sol";
|
||
| 9 |
import {EmptyRevertContract} from "../../src/test/EmptyRevertContract.sol";
|
||
| 10 | |||
| 11 |
contract TestCurrency is Test {
|
||
| 12 |
uint256 constant initialERC20Balance = 1000 ether; |
||
| 13 |
address constant otherAddress = address(1); |
||
| 14 | |||
| 15 |
Currency nativeCurrency; |
||
| 16 |
Currency erc20Currency; |
||
| 17 |
CurrencyTest currencyTest; |
||
| 18 | |||
| 19 |
function setUp() public {
|
||
| 20 |
currencyTest = new CurrencyTest(); |
||
| 21 |
vm.deal(address(currencyTest), 30 ether); |
||
| 22 |
nativeCurrency = Currency.wrap(address(0)); |
||
| 23 |
MockERC20 token = new MockERC20("TestA", "A", 18);
|
||
| 24 |
token.mint(address(currencyTest), initialERC20Balance); |
||
| 25 |
erc20Currency = Currency.wrap(address(token)); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
function test_fuzz_equals(address a, address b) public pure {
|
||
| 29 |
assertEq(a == b, Currency.wrap(a) == Currency.wrap(b)); |
||
| 30 |
} |
||
| 31 | |||
| 32 |
function test_fuzz_greaterThan(address a, address b) public pure {
|
||
| 33 |
assertEq(a > b, Currency.wrap(a) > Currency.wrap(b)); |
||
| 34 |
} |
||
| 35 | |||
| 36 |
function test_fuzz_lessThan(address a, address b) public pure {
|
||
| 37 |
assertEq(a < b, Currency.wrap(a) < Currency.wrap(b)); |
||
| 38 |
} |
||
| 39 | |||
| 40 |
function test_fuzz_greaterThanOrEqualTo(address a, address b) public pure {
|
||
| 41 |
assertEq(a >= b, Currency.wrap(a) >= Currency.wrap(b)); |
||
| 42 |
} |
||
| 43 | |||
| 44 |
function test_fuzz_balanceOfSelf_native(uint256 amount) public {
|
||
| 45 |
uint256 balanceBefore = address(currencyTest).balance; |
||
| 46 |
amount = bound(amount, 0, balanceBefore); |
||
| 47 |
currencyTest.transfer(nativeCurrency, otherAddress, amount); |
||
| 48 |
assertEq(balanceBefore - amount, address(currencyTest).balance); |
||
| 49 |
assertEq(currencyTest.balanceOfSelf(nativeCurrency), address(currencyTest).balance); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function test_fuzz_balanceOfSelf_token(uint256 amount) public {
|
||
| 53 |
amount = bound(amount, 0, initialERC20Balance); |
||
| 54 |
currencyTest.transfer(erc20Currency, otherAddress, amount); |
||
| 55 |
assertEq(currencyTest.balanceOfSelf(erc20Currency), initialERC20Balance - amount); |
||
| 56 |
assertEq( |
||
| 57 |
currencyTest.balanceOfSelf(erc20Currency), |
||
| 58 |
MockERC20(Currency.unwrap(erc20Currency)).balanceOf(address(currencyTest)) |
||
| 59 |
); |
||
| 60 |
} |
||
| 61 | |||
| 62 |
function test_fuzz_balanceOf_native(uint256 amount) public {
|
||
| 63 |
uint256 currencyBalanceBefore = address(currencyTest).balance; |
||
| 64 |
amount = bound(amount, 0, address(currencyTest).balance); |
||
| 65 |
currencyTest.transfer(nativeCurrency, otherAddress, amount); |
||
| 66 | |||
| 67 |
assertEq(otherAddress.balance, amount); |
||
| 68 |
assertEq(address(currencyTest).balance, currencyBalanceBefore - amount); |
||
| 69 |
assertEq(otherAddress.balance, currencyTest.balanceOf(nativeCurrency, otherAddress)); |
||
| 70 |
} |
||
| 71 | |||
| 72 |
function test_fuzz_balanceOf_token(uint256 amount) public {
|
||
| 73 |
amount = bound(amount, 0, initialERC20Balance); |
||
| 74 |
currencyTest.transfer(erc20Currency, otherAddress, amount); |
||
| 75 |
assertEq(currencyTest.balanceOf(erc20Currency, otherAddress), amount); |
||
| 76 |
assertEq(currencyTest.balanceOfSelf(erc20Currency), initialERC20Balance - amount); |
||
| 77 |
assertEq( |
||
| 78 |
MockERC20(Currency.unwrap(erc20Currency)).balanceOf(otherAddress), |
||
| 79 |
currencyTest.balanceOf(erc20Currency, otherAddress) |
||
| 80 |
); |
||
| 81 |
} |
||
| 82 | |||
| 83 |
function test_isNative_native_returnsTrue() public view {
|
||
| 84 |
assertEq(currencyTest.isNative(nativeCurrency), true); |
||
| 85 |
} |
||
| 86 | |||
| 87 |
function test_isNative_token_returnsFalse() public view {
|
||
| 88 |
assertEq(currencyTest.isNative(erc20Currency), false); |
||
| 89 |
} |
||
| 90 | |||
| 91 |
function test_fuzz_isNative(Currency currency) public view {
|
||
| 92 |
assertEq(currencyTest.isNative(currency), (Currency.unwrap(currency) == address(0))); |
||
| 93 |
} |
||
| 94 | |||
| 95 |
function test_toId_nativeReturns0() public view {
|
||
| 96 |
assertEq(currencyTest.toId(nativeCurrency), uint256(0)); |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function test_fuzz_toId_returnsCurrencyAsUint256(Currency currency) public view {
|
||
| 100 |
assertEq(currencyTest.toId(currency), uint256(uint160(Currency.unwrap(currency)))); |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function test_fromId_0ReturnsNative() public view {
|
||
| 104 |
assertEq(Currency.unwrap(currencyTest.fromId(0)), Currency.unwrap(nativeCurrency)); |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function test_fuzz_fromId_returnsUint256AsCurrency(uint256 id) public view {
|
||
| 108 |
uint160 expectedCurrency = uint160(uint256(type(uint160).max) & id); |
||
| 109 |
assertEq(Currency.unwrap(currencyTest.fromId(id)), address(expectedCurrency)); |
||
| 110 |
} |
||
| 111 | |||
| 112 |
function test_fuzz_fromId_toId_opposites(Currency currency) public view {
|
||
| 113 |
assertEq(Currency.unwrap(currency), Currency.unwrap(currencyTest.fromId(currencyTest.toId(currency)))); |
||
| 114 |
} |
||
| 115 | |||
| 116 |
function test_fuzz_toId_fromId_opposites(uint256 id) public view {
|
||
| 117 |
assertEq(id & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, currencyTest.toId(currencyTest.fromId(id))); |
||
| 118 |
} |
||
| 119 | |||
| 120 |
function test_transfer_noReturnData() public {
|
||
| 121 |
// This contract reverts with no data |
||
| 122 |
EmptyRevertContract emptyRevertingToken = new EmptyRevertContract(); |
||
| 123 |
// the token reverts with no data, so our custom error will be emitted instead |
||
| 124 |
vm.expectRevert(abi.encodeWithSelector(CurrencyLibrary.ERC20TransferFailed.selector, new bytes(0))); |
||
| 125 |
currencyTest.transfer(Currency.wrap(address(emptyRevertingToken)), otherAddress, 100); |
||
| 126 |
} |
||
| 127 | |||
| 128 |
function test_fuzz_transfer_native(uint256 amount) public {
|
||
| 129 |
uint256 balanceBefore = otherAddress.balance; |
||
| 130 |
uint256 contractBalanceBefore = address(currencyTest).balance; |
||
| 131 | |||
| 132 |
if (amount <= contractBalanceBefore) {
|
||
| 133 |
currencyTest.transfer(nativeCurrency, otherAddress, amount); |
||
| 134 |
assertEq(otherAddress.balance, balanceBefore + amount); |
||
| 135 |
assertEq(address(currencyTest).balance, contractBalanceBefore - amount); |
||
| 136 |
} else {
|
||
| 137 |
vm.expectRevert(abi.encodeWithSelector(CurrencyLibrary.NativeTransferFailed.selector, new bytes(0))); |
||
| 138 |
currencyTest.transfer(nativeCurrency, otherAddress, amount); |
||
| 139 |
assertEq(otherAddress.balance, balanceBefore); |
||
| 140 |
} |
||
| 141 |
} |
||
| 142 | |||
| 143 |
function test_fuzz_transfer_token(uint256 amount) public {
|
||
| 144 |
uint256 balanceBefore = currencyTest.balanceOf(erc20Currency, otherAddress); |
||
| 145 | |||
| 146 |
if (amount <= initialERC20Balance) {
|
||
| 147 |
currencyTest.transfer(erc20Currency, otherAddress, amount); |
||
| 148 |
assertEq(currencyTest.balanceOf(erc20Currency, otherAddress), balanceBefore + amount); |
||
| 149 |
assertEq( |
||
| 150 |
MockERC20(Currency.unwrap(erc20Currency)).balanceOf(address(currencyTest)), initialERC20Balance - amount |
||
| 151 |
); |
||
| 152 |
} else {
|
||
| 153 |
// the token reverts with an overflow error message, so this is bubbled up |
||
| 154 |
vm.expectRevert( |
||
| 155 |
abi.encodeWithSelector(CurrencyLibrary.ERC20TransferFailed.selector, stdError.arithmeticError) |
||
| 156 |
); |
||
| 157 |
currencyTest.transfer(erc20Currency, otherAddress, amount); |
||
| 158 |
assertEq(currencyTest.balanceOf(erc20Currency, otherAddress), balanceBefore); |
||
| 159 |
} |
||
| 160 |
} |
||
| 161 |
} |
||
| 162 |
| Lines covered: | 0 / 15 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Slot0, Slot0Library} from "../../src/types/Slot0.sol";
|
||
| 6 | |||
| 7 |
contract TestSlot0 is Test {
|
||
| 8 |
function test_slot0_constants_masks() public pure {
|
||
| 9 |
assertEq(Slot0Library.MASK_160_BITS, type(uint160).max); |
||
| 10 |
assertEq(Slot0Library.MASK_24_BITS, type(uint24).max); |
||
| 11 |
} |
||
| 12 | |||
| 13 |
function test_fuzz_slot0_pack_unpack(uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee) |
||
| 14 |
public |
||
| 15 |
pure |
||
| 16 |
{
|
||
| 17 |
// pack starting from "lowest" field |
||
| 18 |
Slot0 _slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setProtocolFee(protocolFee) |
||
| 19 |
.setLpFee(lpFee); |
||
| 20 | |||
| 21 |
assertEq(_slot0.sqrtPriceX96(), sqrtPriceX96); |
||
| 22 |
assertEq(_slot0.tick(), tick); |
||
| 23 |
assertEq(_slot0.protocolFee(), protocolFee); |
||
| 24 |
assertEq(_slot0.lpFee(), lpFee); |
||
| 25 | |||
| 26 |
// pack starting from "highest" field |
||
| 27 |
_slot0 = Slot0.wrap(bytes32(0)).setLpFee(lpFee).setProtocolFee(protocolFee).setTick(tick).setSqrtPriceX96( |
||
| 28 |
sqrtPriceX96 |
||
| 29 |
); |
||
| 30 | |||
| 31 |
assertEq(_slot0.sqrtPriceX96(), sqrtPriceX96); |
||
| 32 |
assertEq(_slot0.tick(), tick); |
||
| 33 |
assertEq(_slot0.protocolFee(), protocolFee); |
||
| 34 |
assertEq(_slot0.lpFee(), lpFee); |
||
| 35 |
} |
||
| 36 |
} |
||
| 37 |
| Lines covered: | 0 / 0 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {LiquidityAmounts} from "./LiquidityAmounts.sol";
|
||
| 5 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 6 |
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
|
||
| 7 |
import {TickMath} from "../../src/libraries/TickMath.sol";
|
||
| 8 |
import {PoolKey} from "../../src/types/PoolKey.sol";
|
||
| 9 |
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
|
||
| 10 | |||
| 11 |
/// @title Calculate token<>liquidity |
||
| 12 |
/// @notice Helps calculate amounts for bounding fuzz tests |
||
| 13 |
/* |
||
| 14 |
library AmountHelpers {
|
||
| 15 |
function getMaxAmountInForPool( |
||
| 16 |
IPoolManager manager, |
||
| 17 |
IPoolManager.ModifyLiquidityParams memory params, |
||
| 18 |
PoolKey memory key |
||
| 19 |
) public view returns (uint256 amount0, uint256 amount1) {
|
||
| 20 |
PoolId id = PoolIdLibrary.toId(key); |
||
| 21 |
uint128 liquidity = StateLibrary.getLiquidity(manager, id); |
||
| 22 |
(uint160 sqrtPriceX96,,,) = StateLibrary.getSlot0(manager, id); |
||
| 23 | |||
| 24 |
uint160 sqrtPriceX96Lower = TickMath.getSqrtPriceAtTick(params.tickLower); |
||
| 25 |
uint160 sqrtPriceX96Upper = TickMath.getSqrtPriceAtTick(params.tickUpper); |
||
| 26 | |||
| 27 |
amount0 = LiquidityAmounts.getAmount0ForLiquidity(sqrtPriceX96Lower, sqrtPriceX96, liquidity); |
||
| 28 |
amount1 = LiquidityAmounts.getAmount1ForLiquidity(sqrtPriceX96Upper, sqrtPriceX96, liquidity); |
||
| 29 |
} |
||
| 30 |
} |
||
| 31 |
*/ |
||
| 32 |
| Lines covered: | 1 / 13 (7.7%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
library Constants {
|
||
| 5 |
uint160 public constant SQRT_PRICE_1_1 = 79228162514264337593543950336; |
||
| 6 |
√ 1
|
uint160 public constant SQRT_PRICE_1_2 = 56022770974786139918731938227; |
|
| 7 |
uint160 public constant SQRT_PRICE_1_4 = 39614081257132168796771975168; |
||
| 8 |
uint160 public constant SQRT_PRICE_2_1 = 112045541949572279837463876454; |
||
| 9 |
uint160 public constant SQRT_PRICE_4_1 = 158456325028528675187087900672; |
||
| 10 |
uint160 public constant SQRT_PRICE_121_100 = 87150978765690771352898345369; |
||
| 11 | |||
| 12 |
uint256 constant MAX_UINT256 = type(uint256).max; |
||
| 13 |
uint128 constant MAX_UINT128 = type(uint128).max; |
||
| 14 |
uint160 constant MAX_UINT160 = type(uint160).max; |
||
| 15 | |||
| 16 |
address constant ADDRESS_ZERO = address(0); |
||
| 17 | |||
| 18 |
/// 0011 1111 1111 1111 |
||
| 19 |
address payable constant ALL_HOOKS = payable(0x0000000000000000000000000000000000003fFF); |
||
| 20 | |||
| 21 |
uint256 constant TICKS_OFFSET = 4; |
||
| 22 | |||
| 23 |
uint24 constant FEE_LOW = 500; |
||
| 24 |
uint24 constant FEE_MEDIUM = 3000; |
||
| 25 |
uint24 constant FEE_HIGH = 10000; |
||
| 26 | |||
| 27 |
bytes constant ZERO_BYTES = new bytes(0); |
||
| 28 |
} |
||
| 29 |
| Lines covered: | 0 / 11 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: MIT |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Currency} from "../../src/types/Currency.sol";
|
||
| 5 |
import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
|
||
| 6 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 7 | |||
| 8 |
/// @notice Library used to interact with PoolManager.sol to settle any open deltas. |
||
| 9 |
/// To settle a positive delta (a credit to the user), a user may take or mint. |
||
| 10 |
/// To settle a negative delta (a debt on the user), a user make transfer or burn to pay off a debt. |
||
| 11 |
/// @dev Note that sync() is called before any erc-20 transfer in `settle`. |
||
| 12 |
library CurrencySettler {
|
||
| 13 |
/// @notice Settle (pay) a currency to the PoolManager |
||
| 14 |
/// @param currency Currency to settle |
||
| 15 |
/// @param manager IPoolManager to settle to |
||
| 16 |
/// @param payer Address of the payer, the token sender |
||
| 17 |
/// @param amount Amount to send |
||
| 18 |
/// @param burn If true, burn the ERC-6909 token, otherwise ERC20-transfer to the PoolManager |
||
| 19 |
function settle(Currency currency, IPoolManager manager, address payer, uint256 amount, bool burn) internal {
|
||
| 20 |
// for native currencies or burns, calling sync is not required |
||
| 21 |
// short circuit for ERC-6909 burns to support ERC-6909-wrapped native tokens |
||
| 22 |
if (burn) {
|
||
| 23 |
manager.burn(payer, currency.toId(), amount); |
||
| 24 |
} else if (currency.isNative()) {
|
||
| 25 |
manager.settle{value: amount}();
|
||
| 26 |
} else {
|
||
| 27 |
manager.sync(currency); |
||
| 28 |
if (payer != address(this)) {
|
||
| 29 |
IERC20Minimal(Currency.unwrap(currency)).transferFrom(payer, address(manager), amount); |
||
| 30 |
} else {
|
||
| 31 |
IERC20Minimal(Currency.unwrap(currency)).transfer(address(manager), amount); |
||
| 32 |
} |
||
| 33 |
manager.settle(); |
||
| 34 |
} |
||
| 35 |
} |
||
| 36 | |||
| 37 |
/// @notice Take (receive) a currency from the PoolManager |
||
| 38 |
/// @param currency Currency to take |
||
| 39 |
/// @param manager IPoolManager to take from |
||
| 40 |
/// @param recipient Address of the recipient, the token receiver |
||
| 41 |
/// @param amount Amount to receive |
||
| 42 |
/// @param claims If true, mint the ERC-6909 token, otherwise ERC20-transfer from the PoolManager to recipient |
||
| 43 |
function take(Currency currency, IPoolManager manager, address recipient, uint256 amount, bool claims) internal {
|
||
| 44 |
claims ? manager.mint(recipient, currency.toId(), amount) : manager.take(currency, recipient, amount); |
||
| 45 |
} |
||
| 46 |
} |
||
| 47 |
| Lines covered: | 0 / 109 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 5 |
import {Hooks} from "../../src/libraries/Hooks.sol";
|
||
| 6 |
import {Currency, CurrencyLibrary} from "../../src/types/Currency.sol";
|
||
| 7 |
import {IHooks} from "../../src/interfaces/IHooks.sol";
|
||
| 8 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 9 |
import {PoolManager} from "../../src/PoolManager.sol";
|
||
| 10 |
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
|
||
| 11 |
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
|
||
| 12 |
import {PoolKey} from "../../src/types/PoolKey.sol";
|
||
| 13 |
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
|
||
| 14 |
import {TickMath} from "../../src/libraries/TickMath.sol";
|
||
| 15 |
import {Constants} from "../utils/Constants.sol";
|
||
| 16 |
import {SortTokens} from "./SortTokens.sol";
|
||
| 17 |
import {PoolModifyLiquidityTest} from "../../src/test/PoolModifyLiquidityTest.sol";
|
||
| 18 |
import {PoolModifyLiquidityTestNoChecks} from "../../src/test/PoolModifyLiquidityTestNoChecks.sol";
|
||
| 19 |
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
|
||
| 20 |
import {SwapRouterNoChecks} from "../../src/test/SwapRouterNoChecks.sol";
|
||
| 21 |
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
|
||
| 22 |
import {PoolNestedActionsTest} from "../../src/test/PoolNestedActionsTest.sol";
|
||
| 23 |
import {PoolTakeTest} from "../../src/test/PoolTakeTest.sol";
|
||
| 24 |
import {PoolSettleTest} from "../../src/test/PoolSettleTest.sol";
|
||
| 25 |
import {PoolClaimsTest} from "../../src/test/PoolClaimsTest.sol";
|
||
| 26 |
import {ActionsRouter} from "../../src/test/ActionsRouter.sol";
|
||
| 27 |
import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol";
|
||
| 28 |
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
|
||
| 29 |
import {
|
||
| 30 |
ProtocolFeeControllerTest, |
||
| 31 |
OutOfBoundsProtocolFeeControllerTest, |
||
| 32 |
RevertingProtocolFeeControllerTest, |
||
| 33 |
OverflowProtocolFeeControllerTest, |
||
| 34 |
InvalidReturnSizeProtocolFeeControllerTest |
||
| 35 |
} from "../../src/test/ProtocolFeeControllerTest.sol"; |
||
| 36 | |||
| 37 |
contract Deployers {
|
||
| 38 |
using LPFeeLibrary for uint24; |
||
| 39 |
using PoolIdLibrary for PoolKey; |
||
| 40 |
using StateLibrary for IPoolManager; |
||
| 41 | |||
| 42 |
// Helpful test constants |
||
| 43 |
bytes constant ZERO_BYTES = Constants.ZERO_BYTES; |
||
| 44 |
uint160 constant SQRT_PRICE_1_1 = Constants.SQRT_PRICE_1_1; |
||
| 45 |
uint160 constant SQRT_PRICE_1_2 = Constants.SQRT_PRICE_1_2; |
||
| 46 |
uint160 constant SQRT_PRICE_2_1 = Constants.SQRT_PRICE_2_1; |
||
| 47 |
uint160 constant SQRT_PRICE_1_4 = Constants.SQRT_PRICE_1_4; |
||
| 48 |
uint160 constant SQRT_PRICE_4_1 = Constants.SQRT_PRICE_4_1; |
||
| 49 | |||
| 50 |
uint160 public constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_PRICE + 1; |
||
| 51 |
uint160 public constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_PRICE - 1; |
||
| 52 | |||
| 53 |
IPoolManager.ModifyLiquidityParams public LIQUIDITY_PARAMS = |
||
| 54 |
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
|
||
| 55 |
IPoolManager.ModifyLiquidityParams public REMOVE_LIQUIDITY_PARAMS = |
||
| 56 |
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18, salt: 0});
|
||
| 57 |
IPoolManager.SwapParams public SWAP_PARAMS = |
||
| 58 |
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
|
||
| 59 | |||
| 60 |
// Global variables |
||
| 61 |
Currency internal currency0; |
||
| 62 |
Currency internal currency1; |
||
| 63 |
IPoolManager manager; |
||
| 64 |
PoolModifyLiquidityTest modifyLiquidityRouter; |
||
| 65 |
PoolModifyLiquidityTestNoChecks modifyLiquidityNoChecks; |
||
| 66 |
SwapRouterNoChecks swapRouterNoChecks; |
||
| 67 |
PoolSwapTest swapRouter; |
||
| 68 |
PoolDonateTest donateRouter; |
||
| 69 |
PoolTakeTest takeRouter; |
||
| 70 |
PoolSettleTest settleRouter; |
||
| 71 |
ActionsRouter actionsRouter; |
||
| 72 | |||
| 73 |
PoolClaimsTest claimsRouter; |
||
| 74 |
PoolNestedActionsTest nestedActionRouter; |
||
| 75 |
ProtocolFeeControllerTest feeController; |
||
| 76 |
RevertingProtocolFeeControllerTest revertingFeeController; |
||
| 77 |
OutOfBoundsProtocolFeeControllerTest outOfBoundsFeeController; |
||
| 78 |
OverflowProtocolFeeControllerTest overflowFeeController; |
||
| 79 |
InvalidReturnSizeProtocolFeeControllerTest invalidReturnSizeFeeController; |
||
| 80 | |||
| 81 |
PoolKey key; |
||
| 82 |
PoolKey nativeKey; |
||
| 83 |
PoolKey uninitializedKey; |
||
| 84 |
PoolKey uninitializedNativeKey; |
||
| 85 | |||
| 86 |
// Update this value when you add a new hook flag. |
||
| 87 |
uint160 hookPermissionCount = 14; |
||
| 88 |
uint160 clearAllHookPermissionsMask = ~uint160(0) << (hookPermissionCount); |
||
| 89 | |||
| 90 |
modifier noIsolate() {
|
||
| 91 |
if (msg.sender != address(this)) {
|
||
| 92 |
(bool success,) = address(this).call(msg.data); |
||
| 93 |
require(success); |
||
| 94 |
} else {
|
||
| 95 |
_; |
||
| 96 |
} |
||
| 97 |
} |
||
| 98 | |||
| 99 |
function deployFreshManager() internal virtual {
|
||
| 100 |
manager = new PoolManager(500000); |
||
| 101 |
} |
||
| 102 | |||
| 103 |
function deployFreshManagerAndRouters() internal {
|
||
| 104 |
deployFreshManager(); |
||
| 105 |
swapRouter = new PoolSwapTest(manager); |
||
| 106 |
swapRouterNoChecks = new SwapRouterNoChecks(manager); |
||
| 107 |
modifyLiquidityRouter = new PoolModifyLiquidityTest(manager); |
||
| 108 |
modifyLiquidityNoChecks = new PoolModifyLiquidityTestNoChecks(manager); |
||
| 109 |
donateRouter = new PoolDonateTest(manager); |
||
| 110 |
takeRouter = new PoolTakeTest(manager); |
||
| 111 |
settleRouter = new PoolSettleTest(manager); |
||
| 112 |
claimsRouter = new PoolClaimsTest(manager); |
||
| 113 |
nestedActionRouter = new PoolNestedActionsTest(manager); |
||
| 114 |
feeController = new ProtocolFeeControllerTest(); |
||
| 115 |
revertingFeeController = new RevertingProtocolFeeControllerTest(); |
||
| 116 |
outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest(); |
||
| 117 |
overflowFeeController = new OverflowProtocolFeeControllerTest(); |
||
| 118 |
invalidReturnSizeFeeController = new InvalidReturnSizeProtocolFeeControllerTest(); |
||
| 119 |
actionsRouter = new ActionsRouter(manager); |
||
| 120 | |||
| 121 |
manager.setProtocolFeeController(feeController); |
||
| 122 |
} |
||
| 123 | |||
| 124 |
// You must have first initialised the routers with deployFreshManagerAndRouters |
||
| 125 |
// If you only need the currencies (and not approvals) call deployAndMint2Currencies |
||
| 126 |
function deployMintAndApprove2Currencies() internal returns (Currency, Currency) {
|
||
| 127 |
Currency _currencyA = deployMintAndApproveCurrency(); |
||
| 128 |
Currency _currencyB = deployMintAndApproveCurrency(); |
||
| 129 | |||
| 130 |
(currency0, currency1) = |
||
| 131 |
SortTokens.sort(MockERC20(Currency.unwrap(_currencyA)), MockERC20(Currency.unwrap(_currencyB))); |
||
| 132 |
return (currency0, currency1); |
||
| 133 |
} |
||
| 134 | |||
| 135 |
function deployMintAndApproveCurrency() internal returns (Currency currency) {
|
||
| 136 |
MockERC20 token = deployTokens(1, 2 ** 255)[0]; |
||
| 137 | |||
| 138 |
address[9] memory toApprove = [ |
||
| 139 |
address(swapRouter), |
||
| 140 |
address(swapRouterNoChecks), |
||
| 141 |
address(modifyLiquidityRouter), |
||
| 142 |
address(modifyLiquidityNoChecks), |
||
| 143 |
address(donateRouter), |
||
| 144 |
address(takeRouter), |
||
| 145 |
address(claimsRouter), |
||
| 146 |
address(nestedActionRouter.executor()), |
||
| 147 |
address(actionsRouter) |
||
| 148 |
]; |
||
| 149 | |||
| 150 |
for (uint256 i = 0; i < toApprove.length; i++) {
|
||
| 151 |
token.approve(toApprove[i], Constants.MAX_UINT256); |
||
| 152 |
} |
||
| 153 | |||
| 154 |
return Currency.wrap(address(token)); |
||
| 155 |
} |
||
| 156 | |||
| 157 |
function deployAndMint2Currencies() internal returns (Currency, Currency) {
|
||
| 158 |
MockERC20[] memory tokens = deployTokens(2, 2 ** 255); |
||
| 159 |
return SortTokens.sort(tokens[0], tokens[1]); |
||
| 160 |
} |
||
| 161 | |||
| 162 |
function deployTokens(uint8 count, uint256 totalSupply) internal returns (MockERC20[] memory tokens) {
|
||
| 163 |
tokens = new MockERC20[](count); |
||
| 164 |
for (uint8 i = 0; i < count; i++) {
|
||
| 165 |
tokens[i] = new MockERC20("TEST", "TEST", 18);
|
||
| 166 |
tokens[i].mint(address(this), totalSupply); |
||
| 167 |
} |
||
| 168 |
} |
||
| 169 | |||
| 170 |
function initPool( |
||
| 171 |
Currency _currency0, |
||
| 172 |
Currency _currency1, |
||
| 173 |
IHooks hooks, |
||
| 174 |
uint24 fee, |
||
| 175 |
uint160 sqrtPriceX96, |
||
| 176 |
bytes memory initData |
||
| 177 |
) internal returns (PoolKey memory _key, PoolId id) {
|
||
| 178 |
_key = PoolKey(_currency0, _currency1, fee, fee.isDynamicFee() ? int24(60) : int24(fee / 100 * 2), hooks); |
||
| 179 |
id = _key.toId(); |
||
| 180 |
manager.initialize(_key, sqrtPriceX96, initData); |
||
| 181 |
} |
||
| 182 | |||
| 183 |
function initPool( |
||
| 184 |
Currency _currency0, |
||
| 185 |
Currency _currency1, |
||
| 186 |
IHooks hooks, |
||
| 187 |
uint24 fee, |
||
| 188 |
int24 tickSpacing, |
||
| 189 |
uint160 sqrtPriceX96, |
||
| 190 |
bytes memory initData |
||
| 191 |
) internal returns (PoolKey memory _key, PoolId id) {
|
||
| 192 |
_key = PoolKey(_currency0, _currency1, fee, tickSpacing, hooks); |
||
| 193 |
id = _key.toId(); |
||
| 194 |
manager.initialize(_key, sqrtPriceX96, initData); |
||
| 195 |
} |
||
| 196 | |||
| 197 |
function initPoolAndAddLiquidity( |
||
| 198 |
Currency _currency0, |
||
| 199 |
Currency _currency1, |
||
| 200 |
IHooks hooks, |
||
| 201 |
uint24 fee, |
||
| 202 |
uint160 sqrtPriceX96, |
||
| 203 |
bytes memory initData |
||
| 204 |
) internal returns (PoolKey memory _key, PoolId id) {
|
||
| 205 |
(_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96, initData); |
||
| 206 |
modifyLiquidityRouter.modifyLiquidity{value: msg.value}(_key, LIQUIDITY_PARAMS, ZERO_BYTES);
|
||
| 207 |
} |
||
| 208 | |||
| 209 |
function initPoolAndAddLiquidityETH( |
||
| 210 |
Currency _currency0, |
||
| 211 |
Currency _currency1, |
||
| 212 |
IHooks hooks, |
||
| 213 |
uint24 fee, |
||
| 214 |
uint160 sqrtPriceX96, |
||
| 215 |
bytes memory initData, |
||
| 216 |
uint256 msgValue |
||
| 217 |
) internal returns (PoolKey memory _key, PoolId id) {
|
||
| 218 |
(_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96, initData); |
||
| 219 |
modifyLiquidityRouter.modifyLiquidity{value: msgValue}(_key, LIQUIDITY_PARAMS, ZERO_BYTES);
|
||
| 220 |
} |
||
| 221 | |||
| 222 |
// Deploys the manager, all test routers, and sets up 2 pools: with and without native |
||
| 223 |
function initializeManagerRoutersAndPoolsWithLiq(IHooks hooks) internal {
|
||
| 224 |
deployFreshManagerAndRouters(); |
||
| 225 |
// sets the global currencies and key |
||
| 226 |
deployMintAndApprove2Currencies(); |
||
| 227 |
(key,) = initPoolAndAddLiquidity(currency0, currency1, hooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES); |
||
| 228 |
nestedActionRouter.executor().setKey(key); |
||
| 229 |
(nativeKey,) = initPoolAndAddLiquidityETH( |
||
| 230 |
CurrencyLibrary.NATIVE, currency1, hooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES, 1 ether |
||
| 231 |
); |
||
| 232 |
uninitializedKey = key; |
||
| 233 |
uninitializedNativeKey = nativeKey; |
||
| 234 |
uninitializedKey.fee = 100; |
||
| 235 |
uninitializedNativeKey.fee = 100; |
||
| 236 |
} |
||
| 237 | |||
| 238 |
/// @notice Helper function for a simple ERC20 swaps that allows for unlimited price impact |
||
| 239 |
function swap(PoolKey memory _key, bool zeroForOne, int256 amountSpecified, bytes memory hookData) |
||
| 240 |
internal |
||
| 241 |
returns (BalanceDelta) |
||
| 242 |
{
|
||
| 243 |
// allow native input for exact-input, guide users to the `swapNativeInput` function |
||
| 244 |
bool isNativeInput = zeroForOne && _key.currency0.isNative(); |
||
| 245 |
if (isNativeInput) require(0 > amountSpecified, "Use swapNativeInput() for native-token exact-output swaps"); |
||
| 246 | |||
| 247 |
uint256 value = isNativeInput ? uint256(-amountSpecified) : 0; |
||
| 248 | |||
| 249 |
return swapRouter.swap{value: value}(
|
||
| 250 |
_key, |
||
| 251 |
IPoolManager.SwapParams({
|
||
| 252 |
zeroForOne: zeroForOne, |
||
| 253 |
amountSpecified: amountSpecified, |
||
| 254 |
sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT |
||
| 255 |
}), |
||
| 256 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),
|
||
| 257 |
hookData |
||
| 258 |
); |
||
| 259 |
} |
||
| 260 | |||
| 261 |
/// @notice Helper function to increase balance of pool manager. |
||
| 262 |
/// Uses default LIQUIDITY_PARAMS range. |
||
| 263 |
function seedMoreLiquidity(PoolKey memory _key, uint256 amount0, uint256 amount1) internal {
|
||
| 264 |
(uint160 sqrtPriceX96,,,) = manager.getSlot0(_key.toId()); |
||
| 265 |
uint128 liquidityDelta = LiquidityAmounts.getLiquidityForAmounts( |
||
| 266 |
sqrtPriceX96, |
||
| 267 |
TickMath.getSqrtPriceAtTick(LIQUIDITY_PARAMS.tickLower), |
||
| 268 |
TickMath.getSqrtPriceAtTick(LIQUIDITY_PARAMS.tickUpper), |
||
| 269 |
amount0, |
||
| 270 |
amount1 |
||
| 271 |
); |
||
| 272 | |||
| 273 |
IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({
|
||
| 274 |
tickLower: LIQUIDITY_PARAMS.tickLower, |
||
| 275 |
tickUpper: LIQUIDITY_PARAMS.tickUpper, |
||
| 276 |
liquidityDelta: int128(liquidityDelta), |
||
| 277 |
salt: 0 |
||
| 278 |
}); |
||
| 279 | |||
| 280 |
modifyLiquidityRouter.modifyLiquidity(_key, params, ZERO_BYTES); |
||
| 281 |
} |
||
| 282 | |||
| 283 |
/// @notice Helper function for a simple Native-token swap that allows for unlimited price impact |
||
| 284 |
function swapNativeInput( |
||
| 285 |
PoolKey memory _key, |
||
| 286 |
bool zeroForOne, |
||
| 287 |
int256 amountSpecified, |
||
| 288 |
bytes memory hookData, |
||
| 289 |
uint256 msgValue |
||
| 290 |
) internal returns (BalanceDelta) {
|
||
| 291 |
require(_key.currency0.isNative(), "currency0 is not native. Use swap() instead"); |
||
| 292 |
if (zeroForOne == false) require(msgValue == 0, "msgValue must be 0 for oneForZero swaps"); |
||
| 293 | |||
| 294 |
return swapRouter.swap{value: msgValue}(
|
||
| 295 |
_key, |
||
| 296 |
IPoolManager.SwapParams({
|
||
| 297 |
zeroForOne: zeroForOne, |
||
| 298 |
amountSpecified: amountSpecified, |
||
| 299 |
sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT |
||
| 300 |
}), |
||
| 301 |
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),
|
||
| 302 |
hookData |
||
| 303 |
); |
||
| 304 |
} |
||
| 305 | |||
| 306 |
// to receive refunds of spare eth from test helpers |
||
| 307 |
receive() external payable {}
|
||
| 308 |
} |
||
| 309 |
| Lines covered: | 0 / 11 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {CommonBase} from "forge-std/Base.sol";
|
||
| 5 | |||
| 6 |
abstract contract JavascriptFfi is CommonBase {
|
||
| 7 |
function runScript(string memory scriptName, string memory args) internal returns (bytes memory result) {
|
||
| 8 |
string[] memory inputs = new string[](8); |
||
| 9 | |||
| 10 |
// build ffi command string |
||
| 11 |
inputs[0] = "npm"; |
||
| 12 |
inputs[1] = "--silent"; |
||
| 13 |
inputs[2] = "--prefix"; |
||
| 14 |
inputs[3] = "./test/js-scripts"; |
||
| 15 |
inputs[4] = "run"; |
||
| 16 |
inputs[5] = scriptName; |
||
| 17 |
inputs[6] = "--"; |
||
| 18 |
inputs[7] = args; |
||
| 19 |
result = vm.ffi(inputs); |
||
| 20 |
} |
||
| 21 |
} |
||
| 22 |
| Lines covered: | 0 / 34 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import "../../src/libraries/FullMath.sol"; |
||
| 5 |
import "../../src/libraries/FixedPoint96.sol"; |
||
| 6 | |||
| 7 |
/// @title Liquidity amount functions |
||
| 8 |
/// @notice Provides functions for computing liquidity amounts from token amounts and prices |
||
| 9 |
library LiquidityAmounts {
|
||
| 10 |
/// @notice Downcasts uint256 to uint128 |
||
| 11 |
/// @param x The uint258 to be downcasted |
||
| 12 |
/// @return y The passed value, downcasted to uint128 |
||
| 13 |
function toUint128(uint256 x) private pure returns (uint128 y) {
|
||
| 14 |
require((y = uint128(x)) == x, "liquidity overflow"); |
||
| 15 |
} |
||
| 16 | |||
| 17 |
/// @notice Computes the amount of liquidity received for a given amount of token0 and price range |
||
| 18 |
/// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower)) |
||
| 19 |
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary |
||
| 20 |
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary |
||
| 21 |
/// @param amount0 The amount0 being sent in |
||
| 22 |
/// @return liquidity The amount of returned liquidity |
||
| 23 |
function getLiquidityForAmount0(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount0) |
||
| 24 |
internal |
||
| 25 |
pure |
||
| 26 |
returns (uint128 liquidity) |
||
| 27 |
{
|
||
| 28 |
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
||
| 29 |
uint256 intermediate = FullMath.mulDiv(sqrtPriceAX96, sqrtPriceBX96, FixedPoint96.Q96); |
||
| 30 |
return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtPriceBX96 - sqrtPriceAX96)); |
||
| 31 |
} |
||
| 32 | |||
| 33 |
/// @notice Computes the amount of liquidity received for a given amount of token1 and price range |
||
| 34 |
/// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)). |
||
| 35 |
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary |
||
| 36 |
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary |
||
| 37 |
/// @param amount1 The amount1 being sent in |
||
| 38 |
/// @return liquidity The amount of returned liquidity |
||
| 39 |
function getLiquidityForAmount1(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount1) |
||
| 40 |
internal |
||
| 41 |
pure |
||
| 42 |
returns (uint128 liquidity) |
||
| 43 |
{
|
||
| 44 |
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
||
| 45 |
return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtPriceBX96 - sqrtPriceAX96)); |
||
| 46 |
} |
||
| 47 | |||
| 48 |
/// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current |
||
| 49 |
/// pool prices and the prices at the tick boundaries |
||
| 50 |
/// @param sqrtPriceX96 A sqrt price representing the current pool prices |
||
| 51 |
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary |
||
| 52 |
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary |
||
| 53 |
/// @param amount0 The amount of token0 being sent in |
||
| 54 |
/// @param amount1 The amount of token1 being sent in |
||
| 55 |
/// @return liquidity The maximum amount of liquidity received |
||
| 56 |
function getLiquidityForAmounts( |
||
| 57 |
uint160 sqrtPriceX96, |
||
| 58 |
uint160 sqrtPriceAX96, |
||
| 59 |
uint160 sqrtPriceBX96, |
||
| 60 |
uint256 amount0, |
||
| 61 |
uint256 amount1 |
||
| 62 |
) internal pure returns (uint128 liquidity) {
|
||
| 63 |
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
||
| 64 | |||
| 65 |
if (sqrtPriceX96 <= sqrtPriceAX96) {
|
||
| 66 |
liquidity = getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0); |
||
| 67 |
} else if (sqrtPriceX96 < sqrtPriceBX96) {
|
||
| 68 |
uint128 liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0); |
||
| 69 |
uint128 liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1); |
||
| 70 | |||
| 71 |
liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1; |
||
| 72 |
} else {
|
||
| 73 |
liquidity = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1); |
||
| 74 |
} |
||
| 75 |
} |
||
| 76 | |||
| 77 |
/// @notice Computes the amount of token0 for a given amount of liquidity and a price range |
||
| 78 |
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary |
||
| 79 |
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary |
||
| 80 |
/// @param liquidity The liquidity being valued |
||
| 81 |
/// @return amount0 The amount of token0 |
||
| 82 |
function getAmount0ForLiquidity(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity) |
||
| 83 |
internal |
||
| 84 |
pure |
||
| 85 |
returns (uint256 amount0) |
||
| 86 |
{
|
||
| 87 |
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
||
| 88 | |||
| 89 |
return FullMath.mulDiv( |
||
| 90 |
uint256(liquidity) << FixedPoint96.RESOLUTION, sqrtPriceBX96 - sqrtPriceAX96, sqrtPriceBX96 |
||
| 91 |
) / sqrtPriceAX96; |
||
| 92 |
} |
||
| 93 | |||
| 94 |
/// @notice Computes the amount of token1 for a given amount of liquidity and a price range |
||
| 95 |
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary |
||
| 96 |
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary |
||
| 97 |
/// @param liquidity The liquidity being valued |
||
| 98 |
/// @return amount1 The amount of token1 |
||
| 99 |
function getAmount1ForLiquidity(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity) |
||
| 100 |
internal |
||
| 101 |
pure |
||
| 102 |
returns (uint256 amount1) |
||
| 103 |
{
|
||
| 104 |
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
||
| 105 | |||
| 106 |
return FullMath.mulDiv(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96); |
||
| 107 |
} |
||
| 108 | |||
| 109 |
/// @notice Computes the token0 and token1 value for a given amount of liquidity, the current |
||
| 110 |
/// pool prices and the prices at the tick boundaries |
||
| 111 |
/// @param sqrtPriceX96 A sqrt price representing the current pool prices |
||
| 112 |
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary |
||
| 113 |
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary |
||
| 114 |
/// @param liquidity The liquidity being valued |
||
| 115 |
/// @return amount0 The amount of token0 |
||
| 116 |
/// @return amount1 The amount of token1 |
||
| 117 |
function getAmountsForLiquidity( |
||
| 118 |
uint160 sqrtPriceX96, |
||
| 119 |
uint160 sqrtPriceAX96, |
||
| 120 |
uint160 sqrtPriceBX96, |
||
| 121 |
uint128 liquidity |
||
| 122 |
) internal pure returns (uint256 amount0, uint256 amount1) {
|
||
| 123 |
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); |
||
| 124 | |||
| 125 |
if (sqrtPriceX96 <= sqrtPriceAX96) {
|
||
| 126 |
amount0 = getAmount0ForLiquidity(sqrtPriceAX96, sqrtPriceBX96, liquidity); |
||
| 127 |
} else if (sqrtPriceX96 < sqrtPriceBX96) {
|
||
| 128 |
amount0 = getAmount0ForLiquidity(sqrtPriceX96, sqrtPriceBX96, liquidity); |
||
| 129 |
amount1 = getAmount1ForLiquidity(sqrtPriceAX96, sqrtPriceX96, liquidity); |
||
| 130 |
} else {
|
||
| 131 |
amount1 = getAmount1ForLiquidity(sqrtPriceAX96, sqrtPriceBX96, liquidity); |
||
| 132 |
} |
||
| 133 |
} |
||
| 134 |
} |
||
| 135 |
| Lines covered: | 0 / 6 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 5 | |||
| 6 |
import "forge-std/console2.sol"; |
||
| 7 | |||
| 8 |
// Useful for printing out the true values in a fuzz. For failing fuzzes, foundry logs the unsanitized params. |
||
| 9 |
contract Logger {
|
||
| 10 |
function logParams(IPoolManager.ModifyLiquidityParams memory params) public pure {
|
||
| 11 |
console2.log("ModifyLiquidity.tickLower", params.tickLower);
|
||
| 12 |
console2.log("ModifyLiquidity.tickUpper", params.tickUpper);
|
||
| 13 |
console2.log("ModifyLiquidity.liquidityDelta", params.liquidityDelta);
|
||
| 14 |
console2.log("ModifyLiquidity.salt");
|
||
| 15 |
console2.logBytes32(params.salt); |
||
| 16 |
} |
||
| 17 |
} |
||
| 18 |
| Lines covered: | 0 / 8 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {Test} from "forge-std/Test.sol";
|
||
| 5 |
import {Deployers} from "test/utils/Deployers.sol";
|
||
| 6 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 7 |
import {Action} from "src/test/PoolNestedActionsTest.sol";
|
||
| 8 |
import {IHooks} from "src/interfaces/IHooks.sol";
|
||
| 9 | |||
| 10 |
contract NestedActions is Test, Deployers, GasSnapshot {
|
||
| 11 |
Action[] actions; |
||
| 12 | |||
| 13 |
function setUp() public {
|
||
| 14 |
initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0))); |
||
| 15 |
} |
||
| 16 | |||
| 17 |
// Asserts and expected outcomes are tested inside the nestedActionRouter |
||
| 18 | |||
| 19 |
function test_nestedSwap() public {
|
||
| 20 |
actions = [Action.SWAP_AND_SETTLE]; |
||
| 21 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 22 |
} |
||
| 23 | |||
| 24 |
function test_nestedAddLiquidity() public {
|
||
| 25 |
actions = [Action.ADD_LIQUIDITY_AND_SETTLE]; |
||
| 26 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 27 |
} |
||
| 28 | |||
| 29 |
function test_nestedRemoveLiquidity() public {
|
||
| 30 |
actions = [Action.ADD_LIQUIDITY_AND_SETTLE, Action.REMOVE_LIQUIDITY_AND_SETTLE]; |
||
| 31 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 32 |
} |
||
| 33 | |||
| 34 |
function test_nestedDonate() public {
|
||
| 35 |
actions = [Action.DONATE_AND_SETTLE]; |
||
| 36 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 37 |
} |
||
| 38 | |||
| 39 |
function test_nestedInitialize() public {
|
||
| 40 |
actions = [Action.INITIALIZE]; |
||
| 41 |
nestedActionRouter.unlock(abi.encode(actions)); |
||
| 42 |
} |
||
| 43 |
} |
||
| 44 |
| Lines covered: | 0 / 5 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 5 |
import {Currency} from "../../src/types/Currency.sol";
|
||
| 6 | |||
| 7 |
library SortTokens {
|
||
| 8 |
function sort(MockERC20 tokenA, MockERC20 tokenB) |
||
| 9 |
internal |
||
| 10 |
pure |
||
| 11 |
returns (Currency _currency0, Currency _currency1) |
||
| 12 |
{
|
||
| 13 |
if (address(tokenA) < address(tokenB)) {
|
||
| 14 |
(_currency0, _currency1) = (Currency.wrap(address(tokenA)), Currency.wrap(address(tokenB))); |
||
| 15 |
} else {
|
||
| 16 |
(_currency0, _currency1) = (Currency.wrap(address(tokenB)), Currency.wrap(address(tokenA))); |
||
| 17 |
} |
||
| 18 |
} |
||
| 19 |
} |
||
| 20 |
| Lines covered: | 0 / 42 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.20; |
||
| 3 | |||
| 4 |
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
|
||
| 5 |
import {Test} from "forge-std/Test.sol";
|
||
| 6 |
import {Vm} from "forge-std/Vm.sol";
|
||
| 7 |
import {Hooks} from "../../src/libraries/Hooks.sol";
|
||
| 8 |
import {MockHooks} from "../../src/test/MockHooks.sol";
|
||
| 9 |
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
|
||
| 10 |
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
|
||
| 11 |
import {IHooks} from "../../src/interfaces/IHooks.sol";
|
||
| 12 |
import {Currency} from "../../src/types/Currency.sol";
|
||
| 13 |
import {PoolManager} from "../../src/PoolManager.sol";
|
||
| 14 |
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
|
||
| 15 |
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
|
||
| 16 |
import {Deployers} from "./Deployers.sol";
|
||
| 17 |
import {ProtocolFees} from "../../src/ProtocolFees.sol";
|
||
| 18 |
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
|
||
| 19 |
import {PoolKey} from "../../src/types/PoolKey.sol";
|
||
| 20 |
import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
|
||
| 21 |
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
|
||
| 22 |
import {Constants} from "../utils/Constants.sol";
|
||
| 23 | |||
| 24 |
/// @notice Testing Deployers.swap() and Deployers.swapNativeInput() |
||
| 25 |
contract SwapHelperTest is Test, Deployers, GasSnapshot {
|
||
| 26 |
using PoolIdLibrary for PoolKey; |
||
| 27 |
using Hooks for IHooks; |
||
| 28 | |||
| 29 |
MockHooks mockHooks; |
||
| 30 | |||
| 31 |
function setUp() public {
|
||
| 32 |
MockHooks impl = new MockHooks(); |
||
| 33 |
vm.etch(Constants.ALL_HOOKS, address(impl).code); |
||
| 34 |
mockHooks = MockHooks(Constants.ALL_HOOKS); |
||
| 35 | |||
| 36 |
initializeManagerRoutersAndPoolsWithLiq(mockHooks); |
||
| 37 |
} |
||
| 38 | |||
| 39 |
// --- Deployers.swap() tests --- // |
||
| 40 |
function test_swap_helper_zeroForOne_exactInput() public {
|
||
| 41 |
int256 amountSpecified = -100; |
||
| 42 |
BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 43 |
assertEq(result.amount0(), amountSpecified); |
||
| 44 |
} |
||
| 45 | |||
| 46 |
function test_swap_helper_zeroForOne_exactOutput() public {
|
||
| 47 |
int256 amountSpecified = 100; |
||
| 48 |
BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES); |
||
| 49 |
assertEq(result.amount1(), amountSpecified); |
||
| 50 |
} |
||
| 51 | |||
| 52 |
function test_swap_helper_oneForZero_exactInput() public {
|
||
| 53 |
int256 amountSpecified = -100; |
||
| 54 |
BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES); |
||
| 55 |
assertEq(result.amount1(), amountSpecified); |
||
| 56 |
} |
||
| 57 | |||
| 58 |
function test_swap_helper_oneForZero_exactOutput() public {
|
||
| 59 |
int256 amountSpecified = 100; |
||
| 60 |
BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES); |
||
| 61 |
assertEq(result.amount0(), amountSpecified); |
||
| 62 |
} |
||
| 63 | |||
| 64 |
function test_swap_helper_native_zeroForOne_exactInput() public {
|
||
| 65 |
int256 amountSpecified = -100; |
||
| 66 |
BalanceDelta result = swap(nativeKey, true, amountSpecified, ZERO_BYTES); |
||
| 67 |
assertEq(result.amount0(), amountSpecified); |
||
| 68 |
} |
||
| 69 | |||
| 70 |
function test_swap_helper_native_zeroForOne_exactOutput() public {
|
||
| 71 |
int256 amountSpecified = 100; |
||
| 72 |
vm.expectRevert(); |
||
| 73 |
swap(nativeKey, true, amountSpecified, ZERO_BYTES); |
||
| 74 |
} |
||
| 75 | |||
| 76 |
function test_swap_helper_native_oneForZero_exactInput() public {
|
||
| 77 |
int256 amountSpecified = -100; |
||
| 78 |
BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES); |
||
| 79 |
assertEq(result.amount1(), amountSpecified); |
||
| 80 |
} |
||
| 81 | |||
| 82 |
function test_swap_helper_native_oneForZero_exactOutput() public {
|
||
| 83 |
int256 amountSpecified = 100; |
||
| 84 |
BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES); |
||
| 85 |
assertEq(result.amount0(), amountSpecified); |
||
| 86 |
} |
||
| 87 | |||
| 88 |
// --- Deployers.swapNativeInput() tests --- // |
||
| 89 |
function test_swapNativeInput_helper_zeroForOne_exactInput() public {
|
||
| 90 |
int256 amountSpecified = -100; |
||
| 91 |
BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 100 wei); |
||
| 92 |
assertEq(result.amount0(), amountSpecified); |
||
| 93 |
} |
||
| 94 | |||
| 95 |
function test_swapNativeInput_helper_zeroForOne_exactOutput() public {
|
||
| 96 |
int256 amountSpecified = 100; |
||
| 97 |
BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 200 wei); // overpay |
||
| 98 |
assertEq(result.amount1(), amountSpecified); |
||
| 99 |
} |
||
| 100 | |||
| 101 |
function test_swapNativeInput_helper_oneForZero_exactInput() public {
|
||
| 102 |
int256 amountSpecified = -100; |
||
| 103 |
BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei); |
||
| 104 |
assertEq(result.amount1(), amountSpecified); |
||
| 105 |
} |
||
| 106 | |||
| 107 |
function test_swapNativeInput_helper_oneForZero_exactOutput() public {
|
||
| 108 |
int256 amountSpecified = 100; |
||
| 109 |
BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei); |
||
| 110 |
assertEq(result.amount0(), amountSpecified); |
||
| 111 |
} |
||
| 112 | |||
| 113 |
function test_swapNativeInput_helper_nonnative_zeroForOne_exactInput() public {
|
||
| 114 |
int256 amountSpecified = -100; |
||
| 115 |
vm.expectRevert(); |
||
| 116 |
swapNativeInput(key, true, amountSpecified, ZERO_BYTES, 0 wei); |
||
| 117 |
} |
||
| 118 | |||
| 119 |
function test_swapNativeInput_helper_nonnative_zeroForOne_exactOutput() public {
|
||
| 120 |
int256 amountSpecified = 100; |
||
| 121 |
vm.expectRevert(); |
||
| 122 |
swapNativeInput(key, true, amountSpecified, ZERO_BYTES, 0 wei); |
||
| 123 |
} |
||
| 124 | |||
| 125 |
function test_swapNativeInput_helper_nonnative_oneForZero_exactInput() public {
|
||
| 126 |
int256 amountSpecified = -100; |
||
| 127 |
vm.expectRevert(); |
||
| 128 |
swapNativeInput(key, false, amountSpecified, ZERO_BYTES, 0 wei); |
||
| 129 |
} |
||
| 130 | |||
| 131 |
function test_swapNativeInput_helper_nonnative_oneForZero_exactOutput() public {
|
||
| 132 |
int256 amountSpecified = 100; |
||
| 133 |
vm.expectRevert(); |
||
| 134 |
swapNativeInput(key, false, amountSpecified, ZERO_BYTES, 0 wei); |
||
| 135 |
} |
||
| 136 |
} |
||
| 137 |
| Lines covered: | 0 / 4 (0.0%) |
|---|
| 1 |
// SPDX-License-Identifier: UNLICENSED |
||
| 2 |
pragma solidity ^0.8.24; |
||
| 3 | |||
| 4 |
import "forge-std/Test.sol"; |
||
| 5 | |||
| 6 |
interface IUniswapV3Factory {
|
||
| 7 |
function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); |
||
| 8 |
function enableFeeAmount(uint24 fee, int24 tickSpacing) external; |
||
| 9 |
} |
||
| 10 | |||
| 11 |
interface IUniswapV3Pool {
|
||
| 12 |
function initialize(uint160 sqrtPriceX96) external; |
||
| 13 |
function mint(address recipient, int24 tickLower, int24 tickUpper, uint128 amount, bytes calldata data) |
||
| 14 |
external |
||
| 15 |
returns (uint256 amount0, uint256 amount1); |
||
| 16 |
function burn(int24 tickLower, int24 tickUpper, uint128 amount) |
||
| 17 |
external |
||
| 18 |
returns (uint256 amount0, uint256 amount1); |
||
| 19 |
function swap( |
||
| 20 |
address recipient, |
||
| 21 |
bool zeroForOne, |
||
| 22 |
int256 amountSpecified, |
||
| 23 |
uint160 sqrtPriceLimitX96, |
||
| 24 |
bytes calldata data |
||
| 25 |
) external returns (int256 amount0, int256 amount1); |
||
| 26 |
} |
||
| 27 | |||
| 28 |
interface IUniswapV3MintCallback {
|
||
| 29 |
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata data) external; |
||
| 30 |
} |
||
| 31 | |||
| 32 |
interface IUniswapV3SwapCallback {
|
||
| 33 |
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external; |
||
| 34 |
} |
||
| 35 | |||
| 36 |
abstract contract V3Helper is Test {
|
||
| 37 |
IUniswapV3Factory v3Factory; |
||
| 38 | |||
| 39 |
function setUp() public virtual {
|
||
| 40 |
address deployedAddr; |
||
| 41 |
bytes memory bytecode = vm.readFileBinary("test/bin/v3Factory.bytecode");
|
||
| 42 |
assembly {
|
||
| 43 |
deployedAddr := create(0, add(bytecode, 0x20), mload(bytecode)) |
||
| 44 |
} |
||
| 45 |
v3Factory = IUniswapV3Factory(deployedAddr); |
||
| 46 |
} |
||
| 47 |
} |
||
| 48 |